zoukankan      html  css  js  c++  java
  • yii2获取登录前的页面url地址--电脑和微信浏览器上的实现以及yii2相关源码的学习

    对于一个有登录限制(权限限制)的网站,用户输入身份验证信息以后,验证成功后跳转到登录前的页面是一项很人性化的功能。那么获取登录前的页面地址就很关键,今天在做一个yii2项目的登录调试时发现了一些很有意思的问题,记录下来。

    1,场景描述

    网站SiteA上的页面Page2需要登录后才能查看,Page2的链接放在页面Page1的一个按钮Button上,Page1在登录前后都是可以访问的,SiteA只提供了微信扫码登录的入口。

    2,功能需求

    假定访客User已经在SiteA上注册过,但当前未登录。User在浏览Page1时,如果点击页面内的Button,则会来到扫码登录页。用微信扫码登录成功后则会跳转至Page2。

    3,跳转页面的代码

    在微信授权后要回调的地址中设置好控制器controller和方法callback。

    然后在callback方法中进行用户登录后的逻辑编写,如果登录成功:

    return $this->goBack();

    这么写在电脑的浏览器上访问网站时是没有问题的,可以实现上述的功能需求。但是如果User是用手机在微信中访问SiteA的Page1,然后点击了Button,那么他是不是会像在电脑上那样来到Page2呢?

    今天测试了下,没有跳转到Page2,反而来到了网站的首页。至于原因是什么,现在还不太清楚。不过倒是找到了解决的方法:在微信授权后要回调地址的地址中加上state参数,在state参数中附带上User登录前浏览的页面地址url。这样在callback方法中就可以拿到url,上面登录成功后的页面跳转就可以这么写:

    1 if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') === false) {
    2     // User在pc浏览器中的跳转
    3     return $this->goBack();
    4 } else {
    5     // User在微信浏览器中的跳转
    6     return $this->redirect(url);
    7 }

    4,User登录前浏览的页面地址url该怎么获得

    yii2中提供了一个方法,下面的方法就可以获得登录前的页面url。

    Yii::$app->user->returnUrl;

    5,yii2是如何实现4中的方法和功能的呢?

    4中的方法是在yiiwebUser中定义的:

     1     public function getReturnUrl($defaultUrl = null)
     2     {
     3         $url = Yii::$app->getSession()->get($this->returnUrlParam, $defaultUrl);
     4         if (is_array($url)) {
     5             if (isset($url[0])) {
     6                 return Yii::$app->getUrlManager()->createUrl($url);
     7             } else {
     8                 $url = null;
     9             }
    10         }
    11 
    12         return $url === null ? Yii::$app->getHomeUrl() : $url;
    13     }

    第3行yiiwebSession的get方法:

    1     public function get($key, $defaultValue = null)
    2     {
    3         $this->open();
    4         return isset($_SESSION[$key]) ? $_SESSION[$key] : $defaultValue;
    5     }

    可以看到yii2是从session中获取的 $this->returnUrlParam 作为登录前的浏览页面地址。

    那么它是如何存储的session,又是在什么时间存储的呢?答案都在yiiwebUser和yiiwebSession中。

    yiiwebUser中的setReturnUrl()方法:

    1     public function setReturnUrl($url)
    2     {
    3         Yii::$app->getSession()->set($this->returnUrlParam, $url);
    4     }

     yiiwebUser中的loginRequired()方法中调用了setReturnUrl()方法:

     1     public function loginRequired($checkAjax = true, $checkAcceptHeader = true)
     2     {
     3         $request = Yii::$app->getRequest();
     4         $canRedirect = !$checkAcceptHeader || $this->checkRedirectAcceptable();
     5         if ($this->enableSession
     6             && $request->getIsGet()
     7             && (!$checkAjax || !$request->getIsAjax())
     8             && $canRedirect
     9         ) {
    10             $this->setReturnUrl($request->getUrl());
    11         }
    12         // ......省略的代码
    13     }

    然后在yiifiltersAccessControl中的denyAccess()中又调用了loginRequired()

    1     protected function denyAccess($user)
    2     {
    3         if ($user->getIsGuest()) {
    4             $user->loginRequired();
    5         } else {
    6             throw new ForbiddenHttpException(Yii::t('yii', 'You are not allowed to perform this action.'));
    7         }
    8     }

    然后在yiifiltersAccessControl中的beforeAction()中又调用了denyAccess()。

    AccessControl可以配置在控制器中,也可以配置在yii2应用的配置文件main.php中,如果配置了,那么在每一次调用控制器的action之前都会执行这个beforeAction(),也就会触发session的存储。

    yiiwebUser中设置了默认要存储的url键名

    public $returnUrlParam = '__returnUrl';

    可以看下session中的内容验证下:

    __returnUrl|s:29:"/controller/action?id=value";

    6,再来看下3中的$this->goBack()方法

    yiiwebContorller中

    1     public function goBack($defaultUrl = null)
    2     {
    3         return Yii::$app->getResponse()->redirect(Yii::$app->getUser()->getReturnUrl($defaultUrl));
    4     }

    可以看到它也是跳转到从 Yii::$app->getUser()->getReturnUrl() 获取的url,其实也就是从session中获取的url地址。

    7,疑问

    那么上面的讨论都是基于登录操作(涉及到了登录前后的逻辑),如果一个网站没有登录功能,也用不到权限控制(AccessControl),就更不用session存储url了。嗯,应该是这么回事。不用登录操作的话,也就不会涉及到刚开始提到的页面跳转了。


  • 相关阅读:
    最终项目 XMessenger Servers
    Linux下patch的制作和应用
    谈移动互联网入口
    绑定服务后台播放音频的简单示例
    MOQL操作数(Operand) (三)
    浅析Hibernate映射(二)——关系映射(3)
    【Extjs优化二】 Form表单提交通用
    Delphi Dll(1)
    用Groovy思考 第三章 Groovy开发环境
    JUnit单元测试入门(三)--JUnit简单实例
  • 原文地址:https://www.cnblogs.com/yangtoude/p/yii2-redirect-to-previous-url-after-login-on-pc-and-wechat.html
Copyright © 2011-2022 走看看