yii2 RESTful access_token api 初步搭建2

为了自我学习和交流PHP(jQuery,Linux,lamp,shell,JavaScript,服务器)等一系列的知识,希望光临本博客的人可以进来交流。寻求共同发展。搭建平台。本人博客也有许多的技术文档,希望可以为你提供一些帮助。


QQ群: 191848169   点击链接加入群【PHP技术交流(总群)】



yii2有三种的认证方式:
1、请求参数方式: access token
也即是当作API URL请求参数发送,例如 https://example.com/users?access-token=xxxxxxxx
2、HTTP 基本认证: 发送用户名username和password, 应用在access token可安全存在API使用端的场景.例如,API使用端是运行在一台服务器上的程序
3、OAuth 2: 使用者从认证服务器上获取基于 OAuth2协议的access token,然后通过 HTTP Bearer Tokens 发送到API 服务器。

下面直说前面两种.
第一种方式:
(1)因为RESTful APIs应为无状态的, 当yii\web\User::enableSession为false, 请求中的用户认证状态就不能通过session来保持。

在控制器中重写初始化函数,设置enableSession = false

[php] view plain copy print?
  1. public function init()  
  2. {  
  3.     parent::init();  
  4.     Yii::$app->user->enableSession = false;  

(2)重写behaviors函数,配置authenticator,引入使用的认证方式。

[php] view plain copy print?
  1. yii\filters\auth\QueryParamAuth;  
  2. public function behaviors()  
  3. {  
  4.     $behaviors = parent::behaviors();  
  5.     $behaviors['authenticator'] = [  
  6.         'class' => QueryParamAuth::className(),  
  7.     ];  
  8.     return $behaviors;  
  9. }  
behaviors()这个函数的是定义这个控制器类的行为,也就是每一次访问这个控制器的方法,都会执行这个behaviors中定义的各种行为,认证也是这个流程,我们访问一个api接口时,就会执行yii\filters\auth\QueryParamAuth的这个文件的authenticate()这个方法

(3)我们需要在配置文件中
'user' => [
    'identityClass' => 'api\models\User',
],


指定认证的model类,现在是在api\models\User这个类中,那么我们需要在api\models\User这个类中实现yii\web\IdentityInterface这个类中的所有定义的接口方法
[php] view plain copy print?
  1. namespace api\models;  
  2. use Yii;  
  3. use yii\base\NotSupportedException;  
  4. use yii\behaviors\TimestampBehavior;  
  5. use yii\db\ActiveRecord;  
  6. use yii\web\IdentityInterface;  
  7.   
  8. class User extends ActiveRecord implements IdentityInterface {  
  9.      /** 
  10.      * @inheritdoc 
  11.      */  
  12.     public static function tableName()  
  13.     {  
  14.         return 'users';  
  15.     }  
  16.     /** 
  17.      * @inheritdoc 
  18.      */  
  19.     public static function findIdentity($id)  
  20.     {  
  21.         return static::findOne(['id' => $id'status' => self::STATUS_ACTIVE]);  
  22.     }  
  23.   
  24.     /** 
  25.      * @inheritdoc 
  26.      */  
  27.     public static function findIdentityByAccessToken($token$type = null)  
  28.     {  
  29.         return static::findOne(['access_token' => $token]);  
  30.     }  
  31.   
  32.     //这个就是我们进行yii\filters\auth\QueryParamAuth调用认证的函数,下面会说到。  
  33.     public function loginByAccessToken($accessToken$type) {  
  34.         //查询数据库中有没有存在这个token  
  35.         return static::findIdentityByAccessToken($token$type);  
  36.     }  
  37.   
  38.     /** 
  39.      * Finds user by username 
  40.      * 
  41.      * @param string $username 
  42.      * @return static|null 
  43.      */  
  44.     public static function findByUsername($username)  
  45.     {  
  46.         return static::findOne(['username' => $username'status' => self::STATUS_ACTIVE]);  
  47.     }  
  48.   
  49.   
  50.     /** 
  51.      * @inheritdoc 
  52.      */  
  53.     public function getId()  
  54.     {  
  55.         return $this->getPrimaryKey();  
  56.     }  
  57.   
  58.     /** 
  59.      * @inheritdoc 
  60.      */  
  61.     public function getAuthKey()  
  62.     {  
  63.         return $this->auth_key;  
  64.     }  
  65.   
  66.     /** 
  67.      * @inheritdoc 
  68.      */  
  69.     public function validateAuthKey($authKey)  
  70.     {  
  71.         return $this->getAuthKey() === $authKey;  
  72.     }  
  73. }  
loginByAccessToken()这个函数是我们需要自己定义的函数,因为这个函数在yii\filters\auth\QueryParamAuth的认证类中会调用。
而findIdentityByAccessToken($token, $type = null)这个是接口函数,我们需要实现的,所以就在loginByAccessToken()这个函数中调用他去查询数据表中有没有对应的token存在,这个就是认证过程。

这样子整个认证的过程就已经完成了。例如现在我们的数据表user有一个token=xxxxxxxx,那么我们的客户端取得这个token,
我们只需要在访问的api附带这个token
http://xxxxxxx/api/v1/users?access-token=xxxxxxxxx;
那么这个url访问就会认证通过,可以返回用户列表,如果没有附带token,那么就会返回401,认证失败,不能往下执行。

下面我们来看一下yii\filters\auth\QueryParamAuth这个认证类:
[php] view plain copy print?
  1. /** 
  2.  * @link http://www.yiiframework.com/ 
  3.  * @copyright Copyright (c) 2008 Yii Software LLC 
  4.  * @license http://www.yiiframework.com/license/ 
  5.  */  
  6.   
  7. namespace yii\filters\auth;  
  8.   
  9. /** 
  10.  * QueryParamAuth is an action filter that supports the authentication based on the access token passed through a query parameter. 
  11.  * 
  12.  * @author Qiang Xue  
  13.  * @since 2.0 
  14.  */  
  15. class QueryParamAuth extends AuthMethod  
  16. {  
  17.     /** 
  18.      * @var string the parameter name for passing the access token 
  19.      */  
  20.     public $tokenParam = 'access-token';  
  21.   
  22.   
  23.     /** 
  24.      * @inheritdoc 
  25.      */  
  26.     public function authenticate($user$request$response)  
  27.     {  
  28.         $accessToken = $request->get($this->tokenParam);  
  29.         if (is_string($accessToken)) {  
  30.             $identity = $user->loginByAccessToken($accessToken, get_class($this));  
  31.             if ($identity !== null) {  
  32.                 return $identity;  
  33.             }  
  34.         }  
  35.         if ($accessToken !== null) {  
  36.             $this->handleFailure($response);  
  37.         }  
  38.   
  39.         return null;  
  40.     }  
  41. }  

$tokenParam这个属性是设置url附带的token的参数key,我们可以在behaviors()这个函数中配置修改:
[php] view plain copy print?
  1. public function behaviors() {  
  2.         $behaviors = parent::behaviors();  
  3.         $behaviors['authenticator'] = [  
  4.             'class' => QueryParamAuth::className(),  
  5.             'tokenParam' => 'token'  //例如改为‘token’  
  6.         ];  
  7.         return $behaviors;  
  8. }  
看看认证函数:
public function authenticate($user, $request, $response) {

}
$user其实就是在配置中user组件对应的api\models\User的实例,$request, $response分别是请求组件和响应组件
再看看authenticate()函数里面的这个函数
$identity = $user->loginByAccessToken($accessToken, get_class($this));

loginByAccessToken()函数也就是在api\models\User类中定义的函数,进行token的认证的。

认证通过后就返回return $identity;

那么大家又觉得奇怪,$user, $request, $response这三个参数在这个类中并没有定义,那么他们是从哪里来的呢?
其实我们可以看到这个类是继承yii\filters\auth\AuthMethod这个类的,里面有一个beforeAction()函数
[php] view plain copy print?
  1. public function beforeAction($action)  
  2.     {  
  3.         $response = $this->response ? : Yii::$app->getResponse();  
  4.   
  5.         try {  
  6.             $identity = $this->authenticate(  
  7.                 $this->user ? : Yii::$app->getUser(),  
  8.                 $this->request ? : Yii::$app->getRequest(),  
  9.                 $response  
  10.             );  
  11.         } catch (UnauthorizedHttpException $e) {  
  12.             if ($this->isOptional($action)) {  
  13.                 return true;  
  14.             }  
  15.   
  16.             throw $e;  
  17.         }  
  18.   
  19.         if ($identity !== null || $this->isOptional($action)) {  
  20.             return true;  
  21.         } else {  
  22.             $this->challenge($response);  
  23.             $this->handleFailure($response);  
  24.             return false;  
  25.         }  
  26.     }  

所以我们执行yii\filters\auth\AuthMethod\QueryParamAuth时,也就是执行beforeAction($action)函数,这个函数调用$this->authenticate()这个函数执行,也就是进行操作前的认证。

你可能感兴趣的:(日常学习)