为了自我学习和交流PHP(jQuery,Linux,lamp,shell,JavaScript,服务器)等一系列的知识,希望光临本博客的人可以进来交流。寻求共同发展。搭建平台。本人博客也有许多的技术文档,希望可以为你提供一些帮助。
QQ群: 191848169 点击链接加入群【PHP技术交流(总群)】
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
- public function init()
- {
- parent::init();
- Yii::$app->user->enableSession = false;
(2)重写behaviors函数,配置authenticator,引入使用的认证方式。
- yii\filters\auth\QueryParamAuth;
- public function behaviors()
- {
- $behaviors = parent::behaviors();
- $behaviors['authenticator'] = [
- 'class' => QueryParamAuth::className(),
- ];
- return $behaviors;
- }
(3)我们需要在配置文件中
'user' => [
'identityClass' => 'api\models\User',
],
指定认证的model类,现在是在api\models\User这个类中,那么我们需要在api\models\User这个类中实现yii\web\IdentityInterface这个类中的所有定义的接口方法
- <?php
- namespace api\models;
- use Yii;
- use yii\base\NotSupportedException;
- use yii\behaviors\TimestampBehavior;
- use yii\db\ActiveRecord;
- use yii\web\IdentityInterface;
- class User extends ActiveRecord implements IdentityInterface {
- /**
- * @inheritdoc
- */
- public static function tableName()
- {
- return 'users';
- }
- /**
- * @inheritdoc
- */
- public static function findIdentity($id)
- {
- return static::findOne(['id' => $id, 'status' => self::STATUS_ACTIVE]);
- }
- /**
- * @inheritdoc
- */
- public static function findIdentityByAccessToken($token, $type = null)
- {
- return static::findOne(['access_token' => $token]);
- }
- //这个就是我们进行yii\filters\auth\QueryParamAuth调用认证的函数,下面会说到。
- public function loginByAccessToken($accessToken, $type) {
- //查询数据库中有没有存在这个token
- return static::findIdentityByAccessToken($token, $type);
- }
- /**
- * Finds user by username
- *
- * @param string $username
- * @return static|null
- */
- public static function findByUsername($username)
- {
- return static::findOne(['username' => $username, 'status' => self::STATUS_ACTIVE]);
- }
- /**
- * @inheritdoc
- */
- public function getId()
- {
- return $this->getPrimaryKey();
- }
- /**
- * @inheritdoc
- */
- public function getAuthKey()
- {
- return $this->auth_key;
- }
- /**
- * @inheritdoc
- */
- public function validateAuthKey($authKey)
- {
- return $this->getAuthKey() === $authKey;
- }
- }
而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
- /**
- * @link http://www.yiiframework.com/
- * @copyright Copyright (c) 2008 Yii Software LLC
- * @license http://www.yiiframework.com/license/
- */
- namespace yii\filters\auth;
- /**
- * QueryParamAuth is an action filter that supports the authentication based on the access token passed through a query parameter.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @since 2.0
- */
- class QueryParamAuth extends AuthMethod
- {
- /**
- * @var string the parameter name for passing the access token
- */
- public $tokenParam = 'access-token';
- /**
- * @inheritdoc
- */
- public function authenticate($user, $request, $response)
- {
- $accessToken = $request->get($this->tokenParam);
- if (is_string($accessToken)) {
- $identity = $user->loginByAccessToken($accessToken, get_class($this));
- if ($identity !== null) {
- return $identity;
- }
- }
- if ($accessToken !== null) {
- $this->handleFailure($response);
- }
- return null;
- }
- }
$tokenParam这个属性是设置url附带的token的参数key,我们可以在behaviors()这个函数中配置修改:
- public function behaviors() {
- $behaviors = parent::behaviors();
- $behaviors['authenticator'] = [
- 'class' => QueryParamAuth::className(),
- 'tokenParam' => 'token' //例如改为‘token’
- ];
- return $behaviors;
- }
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()函数
- public function beforeAction($action)
- {
- $response = $this->response ? : Yii::$app->getResponse();
- try {
- $identity = $this->authenticate(
- $this->user ? : Yii::$app->getUser(),
- $this->request ? : Yii::$app->getRequest(),
- $response
- );
- } catch (UnauthorizedHttpException $e) {
- if ($this->isOptional($action)) {
- return true;
- }
- throw $e;
- }
- if ($identity !== null || $this->isOptional($action)) {
- return true;
- } else {
- $this->challenge($response);
- $this->handleFailure($response);
- return false;
- }
- }
所以我们执行yii\filters\auth\AuthMethod\QueryParamAuth时,也就是执行beforeAction($action)函数,这个函数调用$this->authenticate()这个函数执行,也就是进行操作前的认证。