api认证

1. 数据库里面把user表复制一份出来,新表名称为adminuser,里面新加一个字段access_token

2. 修改api/config/main.php

 'user' => [
            'identityClass' => 'common\models\Adminuser',
            'enableAutoLogin' => true,
            'enableSession'=>false,
           // 'identityCookie' => ['name' => '_identity-backend', 'httpOnly' => true],
        ],
       /* 'session' => [
            // this is the name of the session cookie used for login on the backend
            'name' => 'advanced-backend',
        ],*/

3. 在api/controllers/下新建立AdminuserController.php类

<?php
namespace api\controllers;
use yii\rest\ActiveController;
use common\models\Article;
use yii\data\ActiveDataProvider;
use api\models\ApiLoginForm;
use api\models\SignupForm;
use common\models\Adminuser;
use yii\helpers\ArrayHelper;
use yii\filters\auth\QueryParamAuth;
use yii;

class AdminuserController extends ActiveController{
    public $modelClass = 'common\models\Adminuser';
    public function behaviors(){
        return ArrayHelper::merge(parent::behaviors(),[
            'authenticatior'=>[
                'class'=>QueryParamAuth::className(),
                 'optional' => [
                    'login',//客户端第一个访问login操作的时候哪来的token,yii\filters\auth\QueryParamAuth对外提供一个属性,用于过滤不需要验证的action
                    'signup'
                ],

            ]
            ]);
    }
    public function actionLogin(){
        $model = new ApiLoginForm();
        $model->username = \Yii::$app->request->post('username');
        $model->password = \Yii::$app->request->post('password');
        if($model->login()){
            return ['access_token'=>$model->login()];
        }else{
            $model->validate();//带错误信息的模型
            return $model;
        }
    }

    /*public function actionRegister(){
        $model = new Adminuser();
        $model->username="t";
        $model->password='t';
        $model->email="t";
        $model->save();
        return $model;
    }   */
     public function actionRegister(){
        $model = new SignupForm();
        $model->load(Yii::$app->getRequest()->getBodyParams(), '');
        if($model->signup()){
            return ['result'=>'注册成功'];
        }else{
            $model->validate();//带错误信息的模型
            return $model;
        }
    }  
}

4.在api/models/下新加入ApiLoginForm.php模型类(从common/models/LoginForm.php复制)

<?php
namespace api\models;

use Yii;
use yii\base\Model;
use common\models\Adminuser;

/**
 * Login form
 */
class ApiLoginForm extends Model
{
    public $username;
    public $password;
    public $rememberMe = true;

    private $_user;


    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [
            // username and password are both required
            [['username', 'password'], 'required'],
            // password is validated by validatePassword()
            ['password', 'validatePassword'],
        ];
    }

    /**
     * Validates the password.
     * This method serves as the inline validation for password.
     *
     * @param string $attribute the attribute currently being validated
     * @param array $params the additional name-value pairs given in the rule
     */
    public function validatePassword($attribute, $params)
    {
        if (!$this->hasErrors()) {
            $user = $this->getUser();
            if (!$user || !$user->validatePassword($this->password)) {
                $this->addError($attribute, 'Incorrect username or password.');
            }
        }
    }

    public function attributeLabels(){
        return[
            'username'=>'用户名',
            'password'=>'密码',
        ];
    }
    /**
     * Logs in a user using the provided username and password.
     *
     * @return bool whether the user is logged in successfully
     */
    public function login()
    {
        if ($this->validate()) {
            $accessToken = $this->_user->generateAccessToken();
            $this->_user->save();
            return $accessToken;
        }

        return false;
    }

    /**
     * Finds user by [[username]]
     *
     * @return User|null
     */
    protected function getUser()
    {
        if ($this->_user === null) {
            $this->_user = Adminuser::findByUsername($this->username);
        }

        return $this->_user;
    }
}

5.在common/models/下把User.php模型类复制一份命名为Adminuser.php,修改对应的类名及token验证的函数,新加一个生成令牌access-token的函数:

public function generateAccessToken(){
        $this->access_token = Yii::$app->security->generateRandomString();
        return $this->access_token;
    }

public static function findIdentityByAccessToken($token, $type = null)
    {
        return static::findOne(['access_token'=>$token]);
        //throw new NotSupportedException('"findIdentityByAccessToken" is not implemented.');
    }

6.postman-post访问/adminusers/login获取access_token

7.修改api/models/ArticleController.php,加入阀门:

use yii\helpers\ArrayHelper;
use yii\filters\auth\QueryParamAuth;
......
public function behaviors(){
        return ArrayHelper::merge(parent::behaviors(),[
            'authenticatior'=>[
                'class'=>QueryParamAuth::className()
            ]
            ]);
    }

没有加入这个阀门之前,get访问/articles可以获取到所有文章列表,加入这个阀门后,需要带上第6步登录后获取的access_token才可以获取文章列表,需要注意的是,yii2系统默认的get请求上用access-token作为参数,为中划线