Yii2 用户认证相关使用记录

基础使用

首先在应用的配置文件中进行如下配置

'components' => [
        'user' => [
        	//用于获取验证状态的系统类
            'class' => 'yii\web\User',
            //用于获取用户信息的自定义类,继承了model类,并且实现了接口 yii\web\IdentityInterface
            'identityClass' => 'common\models\UserModel',
            //设置cookie名称
            'identityCookie' => ['name' => 'cookiename'],
            //设置cookie有效时长
            'authTimeout' => 72000,
            //登录后的跳转地址
            'loginUrl' => 'login',
            //登录地址。用于access授权过滤下,游客访问需登录的方法是,自动跳转至该地址
            'returnUrl' => '/WLN100/index/index',
        ],

在控制器中使用认证类获取登录的用户信息

class BaseController extends \common\component\Controller{
	public $user_id;
	
	public function beforeAction($action){
		.....
		//判断当页面不是登录页面,且未登录时,调整到登录页面
		if($action->getUniqueId() != 'user/login'){
			Yii::$app->getResponse()->redirect('user/login.html')
			return false;
		}
	}
	public function actionLogin(){
		$this->user_id = Yii::$app->user->id();
		//未登录时,返回的id为NULL
		if(!$user_id){
			//使用账号密码获取用户信息
			$identityClass = UserModel::findOne(['user_name'=>'zhangsan','password'=>'123321']);
			//使用yii\web\User组件获取授权状态
			Yii::$app->user->login(identityClass );
			//调用login后,会把用户的信息写入到组件中,同时也会设置cookie等信息
			//之后的请求,可以直接从组件中获取用户的相关信息
			$this->user_id = Yii::$app->user->id();
		}else(
			Yii::$app->getResponse()->redirect('index/index.html');
		)
	}
}

以上为基础使用,适用于可以使用cookie的场景。

接口使用

当服务为app提供接口时,无法使用cookie,需要使用token,因为无法使用cookie,所以不需要配置相关信息

'components' => [
        'user' => [
        	//用于获取验证状态的系统类
            'class' => 'yii\web\User',
            //用于获取用户信息的自定义类,继承了model类,并且实现了接口 yii\web\IdentityInterface
            'identityClass' => 'common\models\UserModel'
        ],

在基础使用中,我们调用认证组件user获取用户信息后,需要根据用户信息自行验证用户的登录状态

在接口使用中,因为不能使用cookie,需要通过传入的token获取用户信息,而且验证用户登录状态的方式也发生了改变。框架提供了QueryParamAuth行为,来为我们自动验证当前用户的登录状态

class ApiController extends ActiveController{
	public function behaviors() {
        return array_merge(parent::behaviors(), [
            //权限验证
            'authenticator' => yii\filters\auth\QueryParamAuth::class
        ]);
    }
}

行为authenticator会对所有的请求都进行认证,获取用户信息,当不通过时会返回401。但我们需要部分请求可以不经过验证,如登录、首页等公共页面。我们可以在QueryParamAuth中重写父类的isOptional方法,如下

class QueryParamAuth extends AuthMethod{
	.....................
	protected function isOptional($action){
		$url = $action->getUniqueId();//  模块/控制前/方法
		$no_need_url = ['user/index/login','user/index/index'];
		if(in_array($url,$no_need_url)){
			return true;
		}else{
			return false;	
		}
	}
}

这样,当我们通过login方法输入账号密码成功后,后台会返回token。前台拿到token后记录到本地,在之后的请求中带上token,接口就可以通过token自动验证用户的登录状态了

oauth2 使用

当我们想实现单点登录,多个平台通过一个服务获取登录信息时,需要对yii2的认证进行一些改造
首先修改配置文件

$config = [
    'id' => 'app',
    'basePath' => dirname(dirname(__DIR__)),
    'defaultRoute' => 'v1/index/index', //默认路由
    //模块化开发
    'modules' => ['v1'=>'app/modules/v1/Module'],
    //配置oauth2登录为启动组件
    'bootstrap' => [
        'auth2' => [
        	'class' => 'common\auth2',
        ]
    ]
]

OAuth2 .php

class OAuth2 implements BootstrapInterface{
	//cookie名称
	 const AUTHORIZATION_COOKIE_NAME = 'authorization';
	 
	 public function bootstrap($app)
    {
        parent::bootstrap($app);
        //设置用户组件用户对象
        Yii::$app->set('user',[
            'class' => yii\web\User::class,
            'identityClass' => 'common\auth2\user',
            /**
            auth2公用登录页面url和相关参数
            callbackUrl 用于oauth2登录成功后,请求本网站地址,处理验证信息
            redirectUrl 当前请求页面地址,用于等callbackUrl 处理成功后,跳转到原地址
            **/
            'loginUrl' =>$oauth_url.'&redirectUrl='.urlencode(Yii::$app->request->getAbsoluteUrl()).'&callbackUrl='.urlencode(Url::to(['/auth2/callback'],true)),
        ]);
        //清除缓存数据
        Yii::$app->user->setIdentity(null);
        //退出登录时调用用户管理服务器接口删除对应的token使此用户所有登录状态失效
        Yii::$app->user->on(User::EVENT_BEFORE_LOGOUT,function(){
            Yii::$app->response->getCookies()->remove(self::AUTHORIZATION_COOKIE_NAME);
            //删除autho2端用户登录数据
            return true;
        });
		//从cookie中获取auth2回调后,存储的token信息,token是auth2返回的经过jwt加密的字符串
        $authorization = Yii::$app->request->cookies->get(self::AUTHORIZATION_COOKIE_NAME);
        //存储token不为空,且能解析出正确信息时,把解析的信息放入用户验证组件中
        if(!empty($authorization) && $token = JWTHelper::validateToken($authorization->value)){
            $userIdentityData = $token->getClaim('identity');
            /* @var $userIdentity IdentityInterface|Model*/
            //创建一个common\auth2\user对象 ,此处的user类,是根据oauth2返回的用户信息构建的一个model类,继承IdentityInterface,无对应的table
            $userIdentity = Yii::createObject(Yii::$app->user->identityClass);
            //设置userIdentity 类的属性
            $userIdentity->setAttributes((array)$userIdentityData,false);
            //把userIdentity放入user组件,类似Yii::$app->user->login($user);
            Yii::$app->user->setIdentity($userIdentity);
            $authorization->value = (string)$token;
            $authorization->expire = $token->getClaim('exp');
			//设置用户cookie信息,这样就下次请求就可以通过cooke获取用户认证状态
            Yii::$app->response->cookies->add($authorization);
            return;
        }
    }
}

用户首次请求时,通过user组件获取用户信息,若未登录,跳转到oauth2公共登录地址,如下

class BaseController extends Controller {
	public function beforeAction($action) {
        if(!parent::beforeAction($action)){
            return parent::beforeAction($action);
        }
        $id = Yii::$app->user->id;
        if(!$id){
			Yii::$app->getResponse()->redirect(Yii::$app->user->loginUrl);
		}
    }
}

输入账号密码登录后,公共登录平台会请求callback地址,同时携带token等信息,具体代码如下

class CallBackController extends Controller {
	 $request = Yii::$app->request;
	 //获取登录成功后要跳转的地址,在前面的loginUrl中携带,此时传回来并接收
     $redirectUrl = $request->get('redirectUrl');
	 //验证oauth2平台返回的token是否合法,具体代码根据自己使用的平台自行处理
     $token = JWTHelper::validateToken($request->get('authorization'));
     if(empty($token)){
         throw new BadRequestHttpException('无效的authorization');
     }
     //验证成功,把token相关信息存入cookie中
     Yii::$app->response->getCookies()->add(new Cookie([
         'name' => AccountBootstrap::AUTHORIZATION_COOKIE_NAME,
         'httpOnly' => true,
         'value' => $request->get('authorization'),
         'expire' => $token->getClaim('exp') ,
     ]));
	//跳转到登录成功后的页面
     if(empty($redirectUrl)){
         $redirectUrl = '/';
     }
     return $this->redirect($redirectUrl);
}

需要确保callback不需要登录
callback跳转前,token信息已经存入了cookie,跳转到成功页时,框架先执行了启动组件oauth2。组件会解析cookie中的信息,并更新user组件的信息。此时BaseController 中的验证用户登录通过,不会跳转到登录页面,可以执行之后的代码

以上方法适用于cookie可用的场景中,在app接口相关应用中,流程和代码需要进行一些改造

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值