用户登录 - 自动检测登录 ¶
作者:KK
发表日期:2017.01.28
前面提到判断用户登录用Yii::$app->user->isGuest
来确定是否登录
但是通常大多数功能都要登录后才使用,那如果每一个站内功能都写这个if判断肯定是不现实
其实大家也能想到一些技巧来实现,比如定义一个控制器基类,在基类的init方法里做isGuest判断,所有控制器继承它就行了
方法1:官方推荐,用访问过滤器来判断 ¶
其实这并不是我最推荐的方式,但为了顺利把官方的基础知识学一下,我觉得有必要掌握一下这招
官方在过滤器封装好了一套登录校验逻辑,我们可以直接拿来配置一下就能用上,并且对于需求不断变化的应用来说,用这个比较好扩展
还记得过滤器这篇文章里提到的过滤器吧,在做登录授权的时候就是使用官方自带的yii\filters\AccessControl这个“访问控制”过滤器
好了我们假设有个控制器要用,那就在这个控制器里重写父类的behaviors方法:
public function behaviors(){
return [
'access' => [
'class' => 'yii\filters\AccessControl',
'rules' => [ //检测规则
[ //第1条规则
'roles' => ['@'], //角色集合,@表示登录用户
'allow' => true, //是否允许访问
],
[ //第2条规则
'actions' => ['login', 'register'], //针对本控制器的哪些方法ID生效,这两个ID就是针对actionLogin和actionRegister两个方法生效
'roles' => ['?'], //? 表示未登录用户
'allow' => true, //允许未登录用户访问
],
],
],
];
}
配置好后未登录状态下可以运行控制器的login和register方法,不能运行其它方法,会返回HTTP 403,这是访问控制过滤器的基本使用,晚点再慢慢深入掌握它
访问过滤器规则的封装 ¶
虽然重写behaviors方法使用过滤器就能实现登录检测,但这代码行数也不比自己写逻辑的少,而且还要每个控制器去配置这还得了?
那当然还是封装一个基础控制器,其它控制器继承它来实现继承过滤器规则咯
但这样增加了继承体系总感觉有点不好是吧,还可以这样,定义一个Trait,里面就是behaviors方法:
namespace app\lib; trait TraitCheckLogin{ public function behaviors(){ return [ 'access' => [ 'class' => 'yii\filters\AccessControl', 'rules' => [ //检测规则 [ //第1条规则 'roles' => ['@'], //角色集合,@表示登录用户 'allow' => true, //是否允许访问 ], [ //第2条规则 'actions' => ['login', 'register'], //针对本控制器的哪些方法ID生效,这两个ID就是针对actionLogin和actionRegister两个方法生效 'roles' => ['?'], //? 表示未登录用户 'allow' => true, //允许未登录用户访问 ], ], ], ]; } }
然后在各个控制器里加上
use TraitCheckLogin;
就可以了(因为大部分程序员少接触trait这个知识点所以这样讲了)
配置登录地址 ¶
像上面这样使用了AccessControl过滤器后,在未登录的情况下访问时不会自动跳到登录页面,这样的用户体验不好
这里我们其实只要给user组件配置一下
loginUrl
就能让它自动跳过去了:'user' => [ 'identityClass' => 'app\models\User', 'enableAutoLogin' => true, 'loginUrl' => '/login.html', //!!!重点!!! //'loginUrl' => ['site/show-login'], //可以用数组,底层会拿去Url::to处理 //'loginUrl' => 'http://xxx.com/oauth.html', //甚至是绝对地址 ],
方法2:在app初始化的时候就做登录检测,适合中小型的典型应用 ¶
追加到配置文件第一层key(相关知识点:在配置里定义事件):
'on beforeAction' => function($event){
if(!Yii::$app->user->isGuest){
//已经登录就随便他访问吧
return;
}
$isCommonAccessAction = in_array($event->action->controller->module->requestedRoute, [
'user/register',
'user/login',
'site/error',
'site/captcha',
]); //是否不登陆可以访问
if(!$isCommonAccessAction){
$event->isValid = false;
Yii::$app->response->redirect(Yii::$app->user->loginUrl);
}
}