CakePHP 版本 1.2.5
我希望一个用户拥有多个电子邮件地址。
我希望单个用户有一个密码。
我希望用户使用他们的多个电子邮件地址中的任何一个和他们的单一密码登录。
我创建了一个带有 id 和密码字段的用户表。
我创建了一个 user_email_addresses 表,其中包含 id 字段、user_id 字段和 email_address 字段。
问题:
如何最小程度地修改身份验证组件以在 user_email_addresses 表中查找“用户名”(在本例中为“email_address”)以及在 users 表中查找“密码”?
似乎修改 auth 组件中的识别方法就可以做到这一点。但我认为直接修改 auth 组件是一个坏主意 - 关于如何扩展并仍然可能修改识别方法有什么想法吗? http://cakebaker.42dh.com/2009/09/08/extending-cakephps-core-components/ 或者可能指定不同的身份验证对象?
起始行774:
function identify($user = null, $conditions = null) {
if ($conditions === false) {
$conditions = null;
} elseif (is_array($conditions)) {
$conditions = array_merge((array)$this->userScope, $conditions);
} else {
$conditions = $this->userScope;
}
if (empty($user)) {
$user = $this->user();
if (empty($user)) {
return null;
}
} elseif (is_object($user) && is_a($user, 'Model')) {
if (!$user->exists()) {
return null;
}
$user = $user->read();
$user = $user[$this->userModel];
} elseif (is_array($user) && isset($user[$this->userModel])) {
$user = $user[$this->userModel];
}
if (is_array($user) && (isset($user[$this->fields['username']]) || isset($user[$this->userModel . '.' . $this->fields['username']]))) {
if (isset($user[$this->fields['username']]) && !empty($user[$this->fields['username']]) && !empty($user[$this->fields['password']])) {
if (trim($user[$this->fields['username']]) == '=' || trim($user[$this->fields['password']]) == '=') {
return false;
}
$find = array(
$this->userModel.'.'.$this->fields['username'] => $user[$this->fields['username']],
$this->userModel.'.'.$this->fields['password'] => $user[$this->fields['password']]
);
} elseif (isset($user[$this->userModel . '.' . $this->fields['username']]) && !empty($user[$this->userModel . '.' . $this->fields['username']])) {
if (trim($user[$this->userModel . '.' . $this->fields['username']]) == '=' || trim($user[$this->userModel . '.' . $this->fields['password']]) == '=') {
return false;
}
$find = array(
$this->userModel.'.'.$this->fields['username'] => $user[$this->userModel . '.' . $this->fields['username']],
$this->userModel.'.'.$this->fields['password'] => $user[$this->userModel . '.' . $this->fields['password']]
);
} else {
return false;
}
$model =& $this->getModel();
$data = $model->find(array_merge($find, $conditions), null, null, 0);
if (empty($data) || empty($data[$this->userModel])) {
return null;
}
} elseif (!empty($user) && is_string($user)) {
$model =& $this->getModel();
$data = $model->find(array_merge(array($model->escapeField() => $user), $conditions));
if (empty($data) || empty($data[$this->userModel])) {
return null;
}
}
if (!empty($data)) {
if (!empty($data[$this->userModel][$this->fields['password']])) {
unset($data[$this->userModel][$this->fields['password']]);
}
return $data[$this->userModel];
}
return null;
}
AuthComponent::identify()
采用两个参数,$user
和 $conditions
if ($conditions === false) {
$conditions = null;
} elseif (is_array($conditions)) {
$conditions = array_merge((array)$this->userScope, $conditions);
} else {
$conditions = $this->userScope;
}
查看上面的代码片段,如果您将
false
作为 $conditions
传递,该方法将在没有模型条件的情况下执行。
另外,看看其余的代码,如果您传递
$user
类型的 string
值,它不会执行大部分与用户相关的代码,直到它到达这里:
} elseif (!empty($user) && is_string($user)) {
$model =& $this->getModel();
$data = $model->find(array_merge(array($model->escapeField() => $user), $conditions));
if (empty($data) || empty($data[$this->userModel])) {
return null;
}
}
这里它运行
Model::escapeField()
,不带参数,返回转义版本的 User.id
(默认情况下),并将该字段映射到传入的字符串。然后将其与 $conditions
数组合并并执行Model::find()
。
可以肯定地说,如果字符串是用户的 ID 并且没有条件,它每次都会找到具有该 ID 的人。
因此,您应该能够扩展 AuthComponent 来做您想做的事情,如下所示:
// app/controllers/components/app_auth.php
<?php
App::import('Component', 'Auth');
class AppAuthComponent extends AuthComponent {
/**
* Custom user identification
*/
function identify($user=null, $conditions=null) {
// get the model AuthComponent is configured to use
$model =& $this->getModel(); // default is User
// do a query that will find a User record when given successful login data
$user = $model->find('first', array('conditions' => array(
'EmailAddress.' . $this->fields['username'] => $user[$this->userModel][$this->fields['username']],
'User.' . $this->fields['password'] => $user[$this->userModel][$this->fields['password']],
));
// return null if user invalid
if (!$user) {
return null; // this is what AuthComponent::identify would return on failure
}
// call original AuthComponent::identify with string for $user and false for $conditions
return parent::identify($user[$this->userModel][$model->primaryKey], false);
}
}
?>
您必须在应用程序中将所有对 Auth 的引用替换为 AppAuth,除非您遵循这个方便的提示(评论中的方法很好)。