ASP.NET]更简单的方法:FormsAuthentication登录ReturnUrl使用绝对路径

 

被这个问题困扰多年,今天终于找到了更简单的解决方法,分享一下。

问题场景

假设我们在i.cnblogs.com站点的web.config中对FormsAuthentication进行了如下的设置:

<authentication mode="Forms">
<forms name=".cnblogs" loginUrl="https://passport.cnblogs.com/login.aspx" protection="All" path="/"/>
</authentication>

当我们访问一个需要登录后才能访问的URL时,比如:http://i.cnblogs.com/post/list,请求会被重定向至如下的地址:

https://passport.cnblogs.com/login.aspx?ReturnUrl=%2fpost%2flist

瞧!通过ReturnUrl查询参数传递给登录页面的是相对路径——这就是问题所在。由于访问的页面与登录页面不在同一个二级域名下,使用这个相对路径是Return不回来的。

问题的根源

用ILSPY看一下System.Web.Security.FormsAuthentication的代码,立马就能知道问题原因所在:

internal static string GetLoginPage(string extraQueryString, bool reuseReturnUrl)
{
//...
if (text2 == null)
{
text2 = HttpUtility.UrlEncode(current.Request.RawUrl, current.Request.ContentEncoding);
}
text = text + FormsAuthentication.ReturnUrlVar + "=" + text2;
if (!string.IsNullOrEmpty(extraQueryString))
{
text = text + "&" + extraQueryString;
}
return text;
}

由码可见,微软根本就无视了登录页面不在同一个二级域名的基本应用场景,而且一直无视到现在。

以前的解决方法

在当前站点添加一个中转页面,由中转页面重定向至登录页面。

于是,web.config的设置变成了如下的样子,先重定向至当前站点的登录中转页面。

<authentication mode="Forms">
<forms name=".cnblogs" loginUrl="~/account/login" protection="All" path="/"/>
</authentication>

然后,在中转页面使用绝对路径作为ReturnUrl的值,再重定向至真正的登录页面。

中转页面的示例代码如下:

public class AccountController : Controller
{
public ActionResult Login(string ReturnUrl)
{
return Redirect("https://passport.cnblogs.com/login.aspx?ReturnUrl=" +
HttpUtility.UrlEncode("http://" + Request.Url.Host) + ReturnUrl);
}
}

虽然解决了问题,但是对于这样的解决方法,我觉得有些啰嗦,总觉得有更好的解决方法,可是一直没找到。

今天再次面对这个问题时,狠了一下心,竟然有了意外的收获!

更简单的解决方法

Forms验证中,工作在第一线、最苦最累的是System.Web.Security.FormsAuthenticationModule。

它在OnEnter(object source, EventArgs eventArgs)中调用了OnAuthenticate方法:

// System.Web.Security.FormsAuthenticationModule
private void OnEnter(object source, EventArgs eventArgs)
{
//...
this.OnAuthenticate(new FormsAuthenticationEventArgs(context));
//...
}

而在OnAuthenticate()方法中有如下的事件处理:

private void OnAuthenticate(FormsAuthenticationEventArgs e)
{
HttpCookie httpCookie = null;
if (this._eventHandler != null)
{
this._eventHandler(this, e);
}
//...

再找到有关这个事件的代码:

// System.Web.Security.FormsAuthenticationModule
public event FormsAuthenticationEventHandler Authenticate
{
add
{
this._eventHandler = (FormsAuthenticationEventHandler)Delegate.Combine(this._eventHandler, value);
}
remove
{
this._eventHandler = (FormsAuthenticationEventHandler)Delegate.Remove(this._eventHandler, value);
}
}

从这个地方下手,更简单的解决方法就浮出了水面——

在Global.asax.cs中添加如下的代码:

public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
//...
} protected void FormsAuthentication_OnAuthenticate(Object sender,
FormsAuthenticationEventArgs e)
{
if (Request.Cookies[FormsAuthentication.FormsCookieName] == null)
{
Response.Redirect(FormsAuthentication.LoginUrl + "?ReturnUrl=" +
HttpUtility.UrlEncode(e.Context.Request.Url.AbsoluteUri));
}
}
}

web.config中使用原先的设置:

<authentication mode="Forms">
<forms name=".cnblogs" loginUrl="https://passport.cnblogs.com/login.aspx" protection="All" path="/"/>
</authentication>

访问http://i.cnblogs.com/post/list时,会进行如下的重定向:

https://passport.cnblogs.com/login.aspx?ReturnUrl=http%3a%2f%2fi.cnblogs.com/post/list

如果微软继续无视这个问题,我想这就是最简单的解决方法。

 
 
 
标签: ASP.NET

FormsAuthentication登录ReturnUrl使用绝对路径的更多相关文章

  1. [ASP.NET]更简单的方法:FormsAuthentication登录ReturnUrl使用绝对路径

    转自:http://www.cnblogs.com/dudu/p/formsauthentication-returnurl-absoluteuri.html [ASP.NET]更简单的方法:Form ...

  2. FormsAuthentication 登录兼容 IE11 保存cookie

    现象:使用FormsAuthentication进行登录验证,在IE11客户端无法保存cookie 解决方法:在web.config中的forms中增加cookieless="UseCook ...

  3. 【ASP.NET】编程点滴 :ASP.NET身份验证

    ASP.NET实际开发中身份验证 是一个不可回避的问题.在相当一段长的时间内,由于不求甚解,我对这个话题似懂非懂.今天就对它做个简单的小结. Authentication and Authorizat ...

  4. ASP.NET FormsAuthentication跨站点登录时绝对地址返回的问题

    关键字:FormsAuthentication, loginUrl, ReturnUrl, AbsoluteUri 在ASP.NET应用程序中,FormsAuthentication几乎是标配,但Fo ...

  5. 转 asp.net mvc 身份验证中返回绝对路径的ReturnUrl

    原文:http://www.cnblogs.com/hyl8218/archive/2011/11/22/2259116.html 从HttpUnauthorizedResult的源码可以看出,Htt ...

  6. QQ互联登录回调路径错误redirect uri is illegal(100010)

    QQ互联登录设置的路径设置

  7. linux shell中不显示路径了,显示为-bash-4.1#的两种解决办法

    出现这个问题的原因是因为没有配置.bash_profile的问题,或者是我们不小心清空或删除了.bash_profile文件. 办法一:修改 ~/.bash_profile文件 步骤如下: vim ~ ...

  8. 【Linux_Fedora_系统管理系列】_1_用户登录和系统初始配置

    发现一个问题,在FC14 的Firefox浏览器中,编辑和排版好的博文,在windows下用chrome或者猎豹浏览器打开后,排版就变得阅读 不是很容易里,而且经常不经意的断行.不知道园子的管理人员时 ...

  9. Node.js基于Express框架搭建一个简单的注册登录Web功能

    这个小应用使用到了node.js  bootstrap  express  以及数据库的操作 :使用mongoose对象模型来操作 mongodb 如果没了解过的可以先去基本了解一下相关概念~ 首先注 ...

随机推荐

  1. JavaScript语言核心之词法结构

    编程语言的词法结构是一套基础性规则,用来描述如何使用这门语言来编写程序.作为语法的基础,它规定了诸如变量名是什么样的.怎么写注释,以及程序语句之间如何分割的等规则. 1.1字符集 JavaScript ...

  2. Android——保存并读取文件

    Context.MODE_PRIVATE:为默认操作模式,代表该文件是私有数据,仅仅能被应用本身訪问,在该模式下,写入的内容会覆盖原文件的内容,假设想把新写入的内容追加到原文件里.能够使用Contex ...

  3. asp.net学习之扩展GridView

    原文:asp.net学习之扩展GridView 本节讨论如何从现有的控件,进而扩展成强大的,更定制的GridView控件 1.扩展BoundField 默认的BoundField不能显示多文本,文字一 ...

  4. ORACLE 动态注册和静态注册的区别(转)

    1, oracle 10g 用netca方式建立的都默认为动态注册方式2,如果想改为静态注册的方式则在listener.ora 中加入如下内容即可 SID_LIST_LISTENER = (SID_L ...

  5. 用java字节码解释i++和++i(转)

    这几天抽着一些时间,把Java的class文件结构研究了一下,再后来就想起了这个令人厌烦的问题,想从字节码指令的角度看看,java到底是怎么处理这个的 先看一段java代码 package bishi ...

  6. Nyoj 引水工程(最小生成树)

    描述 南水北调工程是优化水资源配置.促进区域协调发展的基础性工程,是新中国成立以来投资额最大.涉及面最广的战略性工程,事关中华民族长远发展.“南水北调工程”,旨在缓解中国华北和西北地区水资源短缺的国家 ...

  7. WebApi统一输出接口

    public class WebApi { /// <summary> /// 成功后的输出 /// </summary> /// <param name="d ...

  8. Swift # 异常处理

    面向轨道编程 - Swift 中的异常处理 问题 在开发过程中,异常处理算是比较常见的问题了. 举一个比较常见的例子:用户修改注册的邮箱,大概分为以下几个步骤: 接收到一个用户的请求:我要修改邮箱地址 ...

  9. JavaScript语法细节——引用与复制

    原文:JavaScript语法细节--引用与复制 我们都知道,JS中变量的赋值有两种方式,最近在折腾自己写的标签栏插件,碰到了很多平时没注意的问题.正好,那边处理清楚了,稍微整理一下关于引用与复制相关 ...

  10. Socket 学习(三)

    前2节,说的是 Server 与 Client 的数据交互.服务端IP.端口固定,客户端 网服务端发送消息的时候,他的Socket对面被服务端获取到了,而且链接没有中断,他当然可以很容易回复信息. 现 ...