CakePHP的验证组件使用2表 [英] CakePHP Auth Component Using 2 Tables

查看:136
本文介绍了CakePHP的验证组件使用2表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

CakePHP的最新版本1.2.5

我想一个用户拥有多个电子邮件地址。结果
我想一个用户拥有一个密码。结果
我想用户登录使用任何其多个电子邮件地址和单一密码的。

我创建了一个用户表ID和密码字段。结果
我已创建了一个ID字段为user_id字段和EMAIL_ADDRESS领域user_email_addresses表。

问:结果
我如何修改AUTH组件微创寻找在这种情况下,EMAIL_ADDRESS中的用户名,在user_email_addresses表和用户表中的密码?

好像修改的身份验证组件的识别方法可能做到这一点。但我认为直接修改AUTH组件是一个坏主意 - 关于如何扩展,仍然可能修改确定方法的任何想法? <一href=\"http://cakebaker.42dh.com/2009/09/08/extending-cakephps-core-components/\">http://cakebaker.42dh.com/2009/09/08/extending-cakephps-core-components/或可能提名一个不同的身份验证的对象?

首发阵容774:

 函数识别($ USER = NULL,$条件= NULL){
如果($条件=== FALSE){
$条件= NULL;
} ELSEIF(is_array($条件)){
$条件= array_merge((阵列)$这个 - &GT; userScope,$条件);
}其他{
$条件= $这个 - &GT; userScope;
}
如果(空($用户)){
$ USER = $这个 - &gt;用户();
如果(空($用户)){
返回null;
}
} ELSEIF(is_object($用户)及和放大器; is_a($用户'模式')){
如果($用户可与GT;!存在()){
返回null;
}
$ USER = $用户自&GT;阅读();
$ USER = $用户[$这个 - &GT;的usermodel]。
} ELSEIF(is_array($用户)及和放大器;使用isset($用户[$这个 - &GT;的usermodel])){
$ USER = $用户[$这个 - &GT;的usermodel]。
}如果(is_array($用户)及及(使用isset($用户[$这个 - &GT;领域[用户名]])||使用isset($用户[$这个 - 方式&gt;的usermodel $这个。。 - &GT;领域[用户名]]))){如果(使用isset($用户[$这个 - &GT;领域[用户名])及和放大器;!空($用户[$这个 - &GT;领域[用户名])及和放大器;!空( $用户[$这个 - &GT;领域['密码'])){
如果(修剪($用户[$这个 - &GT;领域[用户名]])=='='|| TRIM($用户[$这个 - &GT;领域['密码'])=='=' ){
返回false;
}
$找到=阵列(
$这个 - &GT;的usermodel $这个 - 过夜。'。'。场[用户名] =&GT; $用户[$这个 - &GT;领域[用户名],
$这个 - &GT;的usermodel $这个 - 过夜。'。'。场['密码'] =&GT; $用户[$这个 - &GT;领域['密码']
);
} ELSEIF(使用isset($用户[$这个 - &GT;的usermodel $这个 - 过夜。'。'。场[用户名])及和放大器;!空($用户[$这个 - &GT;的usermodel。 。'$这个 - 方式&gt;字段[用户名])){
如果(修剪($用户[$这个 - &GT;的usermodel $这个 - 过夜。'。'。场[用户名]])=='='|| TRIM($用户[$这个 - &GT;的usermodel。 $这个 - &GT'。';字段['密码'])=='='){
返回false;
}
$找到=阵列(
$这个 - &GT;的usermodel $这个 - 过夜。'。'。场[用户名] =&GT; $用户[$这个 - &GT;的usermodel。 '。 。 $这个 - &GT;领域[用户名],
$这个 - &GT;的usermodel $这个 - 过夜。'。'。场['密码'] =&GT; $用户[$这个 - &GT;的usermodel。 '。 。 $这个 - &GT;领域['密码']
);
}其他{
返回false;
}
$模式=安培; $这个 - &GT; getModel();
$数据= $建模&GT;找到(array_merge($发现,$条件),NULL,NULL,0);
如果(空($数据)||空($数据[$这个 - &GT;的usermodel])){
返回null;
}
} ELSEIF(空($用户)及!&安培; IS_STRING($用户)){
$模式=安培; $这个 - &GT; getModel();
$数据= $建模&GT;找到(array_merge(数组($建模&GT; escapeField()=&GT; $用户),$条件));如果(空($数据)||空($数据[$这个 - &GT;的usermodel])){
返回null;
}
}如果(!空($数据)){
如果(空($的数据![$这个 - &GT;的usermodel] [$这个 - &GT;领域['密码'])){
未设置($数据[$这个 - &GT;的usermodel] [$这个 - &GT;领域['密码']);
}
返回$数据[$这个 - &GT;的usermodel]。
}
返回null;
}


解决方案

AuthComponent ::识别()有两个参数, $用户 $条件

 如果($条件=== FALSE){
        $条件= NULL;
} ELSEIF(is_array($条件)){
        $条件= array_merge((阵列)$这个 - &GT; userScope,$条件);
}其他{
        $条件= $这个 - &GT; userScope;
}

看着上面的片段,如果你通过 $条件,该方法将不执行模型的条件。

此外,望着code的休息,如果你通过类型的 $用户字符串,直到它到达这里不执行大部分的用户相关的code的:

 } ELSEIF(空($用户)及!&安培; IS_STRING($用户)){
        $模式=安培; $这个 - &GT; getModel();
        $数据= $建模&GT;找到(array_merge(数组($建模&GT; escapeField()=&GT; $用户),$条件));        如果(空($数据)||空($数据[$这个 - &GT;的usermodel])){
                返回null;
        }
}

下面运行型号:: escapeField(),不带参数,它返回的转义版本 User.id (默认)和该字段中传递字符串映射,它再与 $条件数组合并这并执行模型::寻找()

它应该是安全地说,如果字符串是用户的ID和没有条件,将每一次发现的人与该ID。

因此​​,你应该能够延长AuthComponent做你想要的东西,像这样:

  //应用程序/控制器/组件/ app_auth.php
&LT; PHP
应用::进口('组件','验证');
类AppAuthComponent扩展AuthComponent {
/ **
 *自定义用户身份识别
 * /
    功能识别($ USER = NULL,$条件= NULL){
        //获取模型AuthComponent配置为使用
        $模式=安培; $这个 - &GT; getModel(); //默认为用户
        //给成功登录数据时,做一个查询,会发现一个用户记录
        $ USER = $建模&GT;找到(第一,阵列('条件'=&GT;阵列(
            '电子邮件地址。' 。 $这个 - &GT;领域[用户名] =&GT; $用户[$这个 - &GT;的usermodel] [$这个 - &GT;领域[用户名],
            '用户。' 。 $这个 - &GT;领域['密码'] =&GT; $用户[$这个 - &GT;的usermodel] [$这个 - &GT;领域['密码'],
        ));
        //返回null如果用户无效
        如果(!$ USER){
            返回null; //这是AuthComponent ::确定将返回失败
        }
        //调用原AuthComponent ::用绳子确定$用户和假为$条件
        返回父::识别($用户[$这个 - &GT;的usermodel] [$建模&GT;的Pri​​maryKey],FALSE);
    }
}
?&GT;

您将不得不更换所有引用您的应用程序与AppAuth未与AUTH除非你按照这个的窍门儿(注释中的做法是好的)。

CakePHP Version 1.2.5

I would like a single user to have multiple email addresses.
I would like a single user to have a single password.
I would like users to log in using any of their multiple email addresses and their single password.

I have created a users table with an id and a password field.
I have created a user_email_addresses table with an id field a user_id field and an email_address field.

Question:
How do I modify the auth component minimally to look for the "username" in this case, "email_address", in the user_email_addresses table and the "password" in the users table?

Seems as though modifying the identify method in the auth component might do it. But I think modifying the auth component directly is a bad idea - any ideas on how to extend and still possibly modify the identify method? http://cakebaker.42dh.com/2009/09/08/extending-cakephps-core-components/ or possibly nominate a different authenticate object?

Starting line 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() takes two parameters, $user and $conditions

if ($conditions === false) {
        $conditions = null;
} elseif (is_array($conditions)) {
        $conditions = array_merge((array)$this->userScope, $conditions);
} else {
        $conditions = $this->userScope;
}

Looking at the above snippet, if you pass false as the $conditions, the method will execute with no model conditions.

Also, looking at the rest of the code, if you pass a $user value of type string, it won't execute most of the user-related code until it gets here:

} 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;
        }
}

Here it runs Model::escapeField(), with no parameters, which returns an escaped version of User.id (by default) and maps this field to the string that was passed in. It then merges this with the $conditions array and performs a Model::find().

It should be safe to say that if the string is the user's ID and there are no conditions it will find the person with that ID every time.

As such, you should be able to extend AuthComponent to do what you want like so:

// 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);
    }
}
?>

You will have to replace all references to Auth with AppAuth in your application unless you follow this handy tip (the approach in the comments is nice).

这篇关于CakePHP的验证组件使用2表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆