Yii2 中的自定义身份验证问题
Custom authentication issue in Yii2
我已经为 Yii2 RESTful 项目添加了一个自定义身份验证组件,它正在验证凭据,但它没有将有效的用户对象返回给 \Yii::$app->user
组件如下所示:
public function authenticate($user, $request, $response) {
$bearerToken = \Yii::$app->getRequest()->getQueryParam('bearer_token');
$user = Account::findIdentityByAccessToken($bearerToken);
return $user;
}
帐户模型方法如下所示:
public static function findIdentityByAccessToken($token, $userType = null) {
return static::findOne(['bearer_token' => $token]);
}
在 authenticate() 方法中调试时,我可以看到 $user 是 Account 的预期记录,但是 \Yii::app()->user 似乎是新创建的用户。 \Yii::app()->user->identity 等于 null.
谁能看出我做错了什么?
要登录用户,这还不够:
Account::findIdentityByAccessToken($bearerToken);
你需要在authentificate()
里面调用$user->login($identity)
。例如,查看它是如何在 yii\web\User loginByAccessToken():
中实现的
public function loginByAccessToken($token, $type = null)
{
/* @var $class IdentityInterface */
$class = $this->identityClass;
$identity = $class::findIdentityByAccessToken($token, $type);
if ($identity && $this->login($identity)) {
return $identity;
} else {
return null;
}
}
因此您也可以在您的自定义身份验证方法中调用它:
$identity = $user->loginByAccessToken($accessToken, get_class($this));
参见 yii\filters\auth\QueryParamAuth.
中如何实施的示例
而且您还需要 return $identity
,而不是 $user
。您的代码中也缺少处理失败。查看它是如何在内置的 auth 方法中实现的:
更多来自官方文档:
更新:
没有什么强迫你使用 loginByAccessToken()
,我只是举个例子。
这是我很久以前写的一个自定义验证方法的例子,不确定它是否 100% 安全和真实,但我希望它能帮助你理解这些细节:
自定义身份验证方法:
<?php
namespace api\components;
use yii\filters\auth\AuthMethod;
class HttpPostAuth extends AuthMethod
{
/**
* @see yii\filters\auth\HttpBasicAuth
*/
public $auth;
/**
* @inheritdoc
*/
public function authenticate($user, $request, $response)
{
$username = $request->post('username');
$password = $request->post('password');
if ($username !== null && $password !== null) {
$identity = call_user_func($this->auth, $username, $password);
if ($identity !== null) {
$user->switchIdentity($identity);
} else {
$this->handleFailure($response);
}
return $identity;
}
return null;
}
}
在 REST 控制器中的用法:
/**
* @inheritdoc
*/
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpPostAuth::className(),
'auth' => function ($username, $password) {
$user = new User;
$user->domain_name = $username;
// This will validate password according with LDAP
if (!$user->validatePassword($password)) {
return null;
}
return User::find()->username($username)->one();
},
];
return $behaviors;
}
指定 $auth
可调用也可以在 HttpBasicAuth
中找到。
我已经为 Yii2 RESTful 项目添加了一个自定义身份验证组件,它正在验证凭据,但它没有将有效的用户对象返回给 \Yii::$app->user
组件如下所示:
public function authenticate($user, $request, $response) {
$bearerToken = \Yii::$app->getRequest()->getQueryParam('bearer_token');
$user = Account::findIdentityByAccessToken($bearerToken);
return $user;
}
帐户模型方法如下所示:
public static function findIdentityByAccessToken($token, $userType = null) {
return static::findOne(['bearer_token' => $token]);
}
在 authenticate() 方法中调试时,我可以看到 $user 是 Account 的预期记录,但是 \Yii::app()->user 似乎是新创建的用户。 \Yii::app()->user->identity 等于 null.
谁能看出我做错了什么?
要登录用户,这还不够:
Account::findIdentityByAccessToken($bearerToken);
你需要在authentificate()
里面调用$user->login($identity)
。例如,查看它是如何在 yii\web\User loginByAccessToken():
public function loginByAccessToken($token, $type = null)
{
/* @var $class IdentityInterface */
$class = $this->identityClass;
$identity = $class::findIdentityByAccessToken($token, $type);
if ($identity && $this->login($identity)) {
return $identity;
} else {
return null;
}
}
因此您也可以在您的自定义身份验证方法中调用它:
$identity = $user->loginByAccessToken($accessToken, get_class($this));
参见 yii\filters\auth\QueryParamAuth.
中如何实施的示例而且您还需要 return $identity
,而不是 $user
。您的代码中也缺少处理失败。查看它是如何在内置的 auth 方法中实现的:
更多来自官方文档:
更新:
没有什么强迫你使用 loginByAccessToken()
,我只是举个例子。
这是我很久以前写的一个自定义验证方法的例子,不确定它是否 100% 安全和真实,但我希望它能帮助你理解这些细节:
自定义身份验证方法:
<?php
namespace api\components;
use yii\filters\auth\AuthMethod;
class HttpPostAuth extends AuthMethod
{
/**
* @see yii\filters\auth\HttpBasicAuth
*/
public $auth;
/**
* @inheritdoc
*/
public function authenticate($user, $request, $response)
{
$username = $request->post('username');
$password = $request->post('password');
if ($username !== null && $password !== null) {
$identity = call_user_func($this->auth, $username, $password);
if ($identity !== null) {
$user->switchIdentity($identity);
} else {
$this->handleFailure($response);
}
return $identity;
}
return null;
}
}
在 REST 控制器中的用法:
/**
* @inheritdoc
*/
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpPostAuth::className(),
'auth' => function ($username, $password) {
$user = new User;
$user->domain_name = $username;
// This will validate password according with LDAP
if (!$user->validatePassword($password)) {
return null;
}
return User::find()->username($username)->one();
},
];
return $behaviors;
}
指定 $auth
可调用也可以在 HttpBasicAuth
中找到。