9

CakePHP 1.2.5 版

我希望单个用户拥有多个电子邮件地址。
我希望一个用户有一个密码。
我希望用户使用他们的多个电子邮件地址和他们的单一密码中的任何一个登录。

我创建了一个带有 id 和密码字段的用户表。
我创建了一个 user_email_addresses 表,其中包含一个 id 字段、一个 user_id 字段和一个 email_address 字段。

问题:
在这种情况下,如何修改身份验证组件以在 user_email_addresses 表中查找“用户名”,“email_address”,在用户表中查找“密码”?

似乎修改身份验证组件中的识别方法可能会做到这一点。但我认为直接修改 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;
}
4

1 回答 1

9

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该方法将在没有模型条件的情况下执行。

另外,看看其余的代码,如果你传递一个$usertype 的值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);
    }
}
?>

您必须在应用程序中用 AppAuth 替换所有对 Auth 的引用,除非您遵循这个方便的提示(评论中的方法很好)。

于 2009-11-09T15:39:27.667 回答