从零开始搭建完整的电影全栈系统(四)——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方法。代码如下:
<?phpnamespace 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方法:
<?phpnamespace 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,并修改 代码如下:
<?phpnamespace 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):

版权声明: 本文为 InfoQ 作者【刘强西】的原创文章。
原文链接:【http://xie.infoq.cn/article/b8271599ac67090c4e225b338】。文章转载请联系作者。

刘强西
还未添加个人签名 2019.06.12 加入
还未添加个人简介
评论 (1 条评论)