2015-03-19 203 views
2

我添加了一个自定义验证组件的Yii2 REST风格的项目,它是验证凭据OK,但它没有返回有效的用户对象为\的Yii :: $ APP->用户自定义身份验证问题

的组件是这样的:

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

我可以看到$用户帐户的预期记录在AU调试时thenticate()方法,但\ Yii :: app() - >用户似乎是一个新安装的用户。 \ Yii :: app() - > user-> identity等于null。

任何人都可以看到我在做什么错在这里?

回答

2

要登录的用户,这是不够的:

Account::findIdentityByAccessToken($bearerToken); 

你需要调用$user->login($identity)authentificate()。例如,见它是如何在yii\web\UserloginByAccessToken()实施:

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实现。

而且您还需要返回$identity而不是$user。您的代码中也缺少处理失败。看看它是如何在内置的身份验证方法来实现:

更多来自官方的文档:

更新:

没有强迫你使用loginByAccessToken(),我刚才提到它作为一个例子。

这里是我写的很长一段时间前,不知道这是否是100%的安全和真正的定制身份验证方法的一个例子,但我希望它可以帮助你了解这些细节:

自定义身份验证方法:在REST控制器

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

用法:

/** 
* @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找到。

+0

谢谢。你为我清理了它。我没有重新确认我的auth方法应该调用内置的loginByAccessToken(),而后者会调用我自定义的findIdentityByAccessToken()方法。 我是否也可以通过用户名和密码进行查找,因为我想自定义这些?我看不到找到loginByAccessToken()等价物。 – Dubby 2015-03-19 05:33:09

+0

对不起,上面应该是电子邮件和密码。 – Dubby 2015-03-19 05:49:43

+1

没有什么会强制你使用这种方法。我只是提到这个例子。我用另一个例子更新了答案。 – arogachev 2015-03-19 06:22:03