乐趣区

关于yii:从零开始搭建完整的电影全栈系统四restfulApi用户的认证授权及用户注册

在配置文件 main.php 中设置用户认证类,并正文掉 cookies 和 session 配置,因为 Api 客户端和 WEB 网站不同,通常不能应用 cookies 和 session 维持登录状态。

'user' => [
            'identityClass' => 'common\models\User',
            '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',
        ],*/

实现 Api 用户认证(登录性能)

复制一份 common/models/UserLoginForm 到 common/models 中并改名为 ApiLoginForm,同时将 remember me 和 vitifyCode 等相干性能勾销,并重写 login 办法。代码如下:

<?php
namespace api\models;

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

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

    private $_user;

    public function attributeLabels() // 属性 labels
    {
        return [
            'username' => '用户名',
            'password' => '明码',
            //'rememberMe' => '记住我',
            //'vitifyCode' => '验证码',
        ];
    }
    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            // username and password are both required
            [['username', 'password'], 'required'],
            // rememberMe must be a boolean value
            //['rememberMe', 'boolean'],
            // password is validated by validatePassword()
            ['password', 'validatePassword'],
            //['vitifyCode', 'captcha'], // 验证码验证
        ];
    }

    /**
     * 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.');
            }
        }
    }

    /**
     * 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()) {//            return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
            $access_token = $this->_user->generateAccessToken();
            $this->_user->expire_at=time()+3600*7*24;// 设定 access_token 过期工夫
            $this->_user->save();
            Yii::$app->user->login($this->_user,3600*7*24);
            return $access_token;
        } else {return false;}
    }

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

        return $this->_user;
    }
}

在 common/models User 中实现 generateAccessToken,代码如下:

/**
     * 生成 access_token
     * @return string
     * @throws \yii\base\Exception
     */

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

实现 UserController 控制器,实现 login 办法:

<?php

namespace api\controllers;

use api\models\ApiLoginForm;
use common\models\Article;
use yii\rest\ActiveController;

/**
 * VodDetailController implements the CRUD actions for VodDetail model.
 */
class UserController extends ActiveController
{

    public $modelClass = 'common\models\User';
    public function actionLogin()
    {$model = new ApiLoginForm();
        /* $model->username = $_POST['username'];
         $model->password = $_POST['password'];*/
        // 应用 getBodyParams 解决 POST 申请
        $model->load(\Yii::$app->getRequest()->getBodyParams(),'');
        if ($model->login()) {return ['access_token' => $model->login()];
        } else {$model->validate();
            return $model;
        }
    }
}

配置好 url 丑化:

 [
                    'class' => 'yii\rest\UrlRule',
                    'controller' => 'user',
                    'pluralize' => false,// 拜访资源不须要加 s
                    'extraPatterns' => [
                        'POST login' => 'login',
                        'POST signup' => 'signup',
                    ],
                ]

测试登录 api 顺利取得 accessToken:

认证状态的维持


维持认证状态,就是客户端如何⽤ accesstoken 这个令
牌,去拜访服务端所提供的服务。
1,增加 QueryParamAuth 过滤器,在 VideoDetailController:

public function behaviors()
{return ArrayHelper::merge(parent::behaviors(), [
 'authenticatior' => ['class' => QueryParamAuth::className()
 ]
 ]);
}


能够看出认证曾经失效。

咱们带上无效的 access-token 去测试:

提醒咱们,要想顺利通过验证必须在 common\models\User.php 实现个 findIdentityByAccessToken 办法。实现该办法:

public static function findIdentityByAccessToken($token, $type = null)
    {return static::find()
            ->where(['access_token'=>$token,'status'=>self::STATUS_ACTIVE])
            ->andWhere(['>','expire_at',time()])
            ->one();}

再次带上 access-token 去测试,能够看出顺利失去想要的数据了:

咱们还能够指定须要认证能力拜访的动作。比方列表页不须要认证,详情须要:

public function behaviors()
    {return ArrayHelper::merge(parent::behaviors(), [
            'authenticatior' => ['class' => QueryParamAuth::className(),
                'only' => ['view'],
            ],

        ]);
    }

Yii RestfulApi 认证能够参考:Yii RestfulApi 认证

过滤器能够参考:过滤器

用户注册实现

复制一份 frontend/models/SignupForm 到 common/models 中并改名为 ApiSignupForm, 并批改 代码如下:

<?php
namespace api\models;

use common\models\User;
use yii\base\Model;

/**
 * Signup form
 */
class ApiSignupForm extends Model
{
    public $username;
    public $email;
    public $password;
    public $password_repeat;


    /**
     * @inheritdoc
     */
    public function rules()
    {
        return [['username', 'trim'],
            ['username', 'required'],
            ['username', 'unique', 'targetClass' => '\common\models\User', 'message' => '用户名已被占用.'],
            ['username', 'string', 'min' => 2, 'max' => 255],

            ['email', 'trim'],
            ['email', 'required'],
            ['email', 'email'],
            ['email', 'string', 'max' => 255],
            ['email', 'unique', 'targetClass' => '\common\models\User', 'message' => 'Email 已被占用.'],

            ['password', 'required'],
            ['password_repeat', 'required'],
            ['password', 'string', 'min' => 6],
            ['password_repeat','compare','compareAttribute'=>'password','message'=>'两次输出的明码不统一!'],
            /*['realname','required'],
            ['realname','string','max'=>128],*/
        ];
    }

    public function attributeLabels()
    {
        return [
            'username' => '用户名',
            //'realname' => '姓名',
            'password' => '明码',
            'password_repeat'=>'反复明码',
            'email' => '电子邮箱',
        ];
    }

    /**
     * Signs user up.
     *
     * @return User|null the saved model or null if saving fails
     * @throws \yii\base\Exception
     */
    public function signup()
    {if (!$this->validate()) {return null;}
        
        $user = new User();
        $user->username = $this->username;
        $user->email = $this->email;
        //$user->realname=$this->realname;
        $user->setPassword($this->password);
        $user->generateAuthKey();
        
        return $user->save() ? $user : null;}
}

在 UserController 中实现 signup 办法:

public function actionSignup()
    {$model = new ApiSignupForm();
        $model->load(\Yii::$app->getRequest()->getBodyParams(),'');
        if ($model->signup()) {return ['result' =>'注册胜利'];
        } else {$model->validate();
            return $model;
        }
    }

配置 Url 丑化:

 [
                    'class' => 'yii\rest\UrlRule',
                    'controller' => 'user',
                    'pluralize' => false,// 拜访资源不须要加 s
                    'extraPatterns' => [
                        'POST login' => 'login',
                        'POST signup' => 'signup',
                    ],
                ]

测试:

欢送各位大佬入裙探讨(879782113):

退出移动版