2015-03-19 131 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