对于一个有登录限制(权限限制)的网站,用户输入身份验证信息以后,验证成功后跳转到登录前的页面是一项很人性化的功能。那么获取登录前的页面地址就很关键,今天在做一个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,上面登录成功后的页面跳转就可以这么写:

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

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

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

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

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

4中的方法是在yii\web\User中定义的:

     public function getReturnUrl($defaultUrl = null)
{
$url = Yii::$app->getSession()->get($this->returnUrlParam, $defaultUrl);
if (is_array($url)) {
if (isset($url[0])) {
return Yii::$app->getUrlManager()->createUrl($url);
} else {
$url = null;
}
} return $url === null ? Yii::$app->getHomeUrl() : $url;
}

第3行yii\web\Session的get方法:

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

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

那么它是如何存储的session,又是在什么时间存储的呢?答案都在yii\web\User和yii\webSession中。

yii\web\User中的setReturnUrl()方法:

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

yii\web\User中的loginRequired()方法中调用了setReturnUrl()方法:

     public function loginRequired($checkAjax = true, $checkAcceptHeader = true)
{
$request = Yii::$app->getRequest();
$canRedirect = !$checkAcceptHeader || $this->checkRedirectAcceptable();
if ($this->enableSession
&& $request->getIsGet()
&& (!$checkAjax || !$request->getIsAjax())
&& $canRedirect
) {
$this->setReturnUrl($request->getUrl());
}
// ......省略的代码
}

然后在yii\filters\AccessControl中的denyAccess()中又调用了loginRequired()

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

然后在yii\filters\AccessControl中的beforeAction()中又调用了denyAccess()。

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

yii\web\User中设置了默认要存储的url键名

public $returnUrlParam = '__returnUrl';

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

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

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

yii\web\Contorller中

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

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

7,疑问

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


yii2获取登录前的页面url地址--电脑和微信浏览器上的实现以及yii2相关源码的学习的更多相关文章

  1. Magento获取当前页面URL地址

    Magento获取当前页面URL地址 http://www.sunhaibing.com/?p=1260 在Magento中,可以通过core/url助手类中的getCurrentUrl()方法获取当 ...

  2. js/jquery获取当前页面URL地址并判断URL字符串中是否包含某个具体值

    js/jquery获取当前页面URL地址并判断URL字符串中是否包含某个具体值本文介绍jquery/js获取当前页面url地址的方法,在jquery与js中获取当前页面url方法是一样的,因为jque ...

  3. 织梦DedeCms获取当前页面URL地址的调用方法

    织梦内容页如何调用当前页面url?相信很多对织梦感兴趣的朋友都会去考虑这个问题:在文章内容中加入本文链接,除了 保护自己版权外还可以增加网站的外链收录.网上这方面的帖子一搜一大堆,但多数都只能调用相对 ...

  4. yii2怎样写规则可以隐藏url地址里的控制器名字

    yii2怎样写规则可以隐藏url地址里的控制器名字,例如现在的是***.com/site/index.html要变成***.com/index.html '<action:index>.h ...

  5. JS window对象 History 对象 history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能。语法: window.history.[属性|方法]

    History 对象 history对象记录了用户曾经浏览过的页面(URL),并可以实现浏览器前进与后退相似导航的功能. 注意:从窗口被打开的那一刻开始记录,每个浏览器窗口.每个标签页乃至每个框架,都 ...

  6. h5微信页面在手机微信端和微信web开发者工具中都能正常显示,但是在pc端微信浏览器上打不开(显示空白)

    h5微信页面在手机微信和微信开发者工具中都能正常显示,但是在pc端微信浏览器上打不开或者数据加载不出来. 原因:pc端微信浏览器不支持ES6语法,我的代码中使用了一些ES6的特性 解决:将ES6转换为 ...

  7. JavaScript中关于页面URL地址的获取

    1 window.location.host; //返回url的主机部分,例如 www.xxx.com window.location.hostname; //返回url的主机名,例如 www.xxx ...

  8. 跨域下使用获取iframe的父页面URL

    通常情况下,我们获取iframe父页面的url很简单:parent.location或top.location即可,但前提是它们遵循同源策略. 当iframe与父页面不属于同一个域名时,像上面的获取会 ...

  9. 用JavaScript获取一个超链接的绝对URL地址

    对于Web程序员来说,处理简单的URL格式也许会成为一场噩梦.试想一下,一个网址里有很多组成部分都会影响你对它的解析方法: 是否以/字符开头 是否以//开头 是否以?号开头 是否以#号开头 …等等 当 ...

随机推荐

  1. 最好的.NET开源免费ZIP库DotNetZip(.NET组件介绍之三)

    在项目开发中,除了对数据的展示更多的就是对文件的相关操作,例如文件的创建和删除,以及文件的压缩和解压.文件压缩的好处有很多,主要就是在文件传输的方面,文件压缩的好处就不需要赘述,因为无论是开发者,还是 ...

  2. Spark读写Hbase的二种方式对比

    作者:Syn良子 出处:http://www.cnblogs.com/cssdongl 转载请注明出处 一.传统方式 这种方式就是常用的TableInputFormat和TableOutputForm ...

  3. Kooboo CMS技术文档之四:Kooboo CMS的站点组成部分

    Kooboo CMS本着功能独立分离的原则,将站点分为三部分组成:用户管理,站点管理和内容数据库管理.各个功能之间既可独立使用,也可以容易组成在一起形成一个完整的系统. 用户管理 管理整个系统内的用户 ...

  4. 纯javaScript、jQuery实现个性化图片轮播

    纯javaScript实现个性化图片轮播 轮播原理说明<如上图所示>: 1. 画布部分(可视区域)属性说明:overflow:hidden使得超出画布部分隐藏或说不可见.position: ...

  5. 【centos7常用技巧】RPM打包

    一.RPM打包的目的 1.当目标机中不存在编译环境时,可以先在本地环境中编译打包,然后直接在目标机中用rpm -ivh *.rpm安装即可. 2.当需要在目标机中安装多个软件或者增加多个文件时,可以将 ...

  6. ios 类似微信红点显示功能

    设计思路:给UIView增加一个分类 所有的视图都可以根据需要来进行红点显示 #import <UIKit/UIKit.h> @interface UIView (CHRRedDot) @ ...

  7. JBPM

    JBPM简介 什么是jbpm JBPM,全称是Java Business Process Management(业务流程管理),它是覆盖了业务流程管理.工作流.服务协作等领域的一个开源的.灵活的.易扩 ...

  8. No plugin found for prefix ‘jetty’ in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories

    maven配置文件(最大的那个)的<pluginGroups></pluginGroups>增加一行如下<pluginGroups><pluginGroup& ...

  9. 使用 GCC 和 GNU Binutils 编写能在 x86 实模式运行的 16 位代码

    不可否认,这次的标题有点长.之所以把标题写得这么详细,主要是为了搜索引擎能够准确地把确实需要了解 GCC 生成 16 位实模式代码方法的朋友带到我的博客.先说一下背景,编写能在 x86 实模式下运行的 ...

  10. 2000条你应知的WPF小姿势 基础篇<51-56 依赖属性>

    前一阵子由于个人生活原因,具体见上一篇,耽搁了一阵子,在这里也十分感谢大家支持和鼓励.现在开始继续做WPF2000系列. 在正文开始之前需要介绍一个人:Sean Sexton. 来自明尼苏达双城的软件 ...