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. Oracle中使用Entity Framework 6.x Code-First

    Oracle中使用Entity Framework 6.x Code-First方式开发 去年写过一篇EF的简单学习笔记,当时EF还不支持Oracle的Code-First开发模式,今天无意又看了下O ...

  2. 一个奇怪的注意事项TNS-12545 TNS-12560 TNS-00515

    近来的reportDB无法从一开始就与系统收听,比较奇怪的现象. 由于server有听众的一个实例上正常启动,这是不是从开始监听器的实例手动启动是正常的.所以写下来未能找到离奇写的原因. 1.故障现象 ...

  3. ssh 综合

    文件夹结构: 搭建项目: 1.创建web项目 2.创建各种包. com.atguigu.surveypark.dao.impl com.atguigu.surveypark.model com.atg ...

  4. 使用ArcGIS API for Silverlight 进行复合多条件空间查询

    原文:使用ArcGIS API for Silverlight 进行复合多条件空间查询 这两天帮网上认识的一个兄弟做了一个查询的示例,多多少少总结一下,在此和大家分享. 为什么说是复合多条件呢?因为进 ...

  5. HDU 1080 Human Gene Functions--DP--(变形最长公共子)

    意甲冠军:该基因序列的两端相匹配,四种不同的核苷酸TCGA有不同的分值匹配.例如T-G比分是-2,它也可以被加入到空格,空洞格并且还具有一个相应的核苷酸匹配分值,求最大比分 分析: 在空气中的困难格的 ...

  6. SQL2005性能分析一些细节功能你是否有用到?

    原文:SQL2005性能分析一些细节功能你是否有用到? 我相信很多朋友对现在越来越大的数据量而感到苦恼,可是总要面对现实啊,包括本人在内的数据库菜鸟们在开发B/S程序时,往往只会关心自己的数据是否正确 ...

  7. 让你的Windows不断重启的C语言代码

    原文:让你的Windows不断重启的C语言代码 没有写Linux的原因是因为搞不定Linux下的权限问题,而Windows下基本上使用电脑的用户都是管理员,所以钻个空了,不多说下面是代码#includ ...

  8. Linux httpd 跳转简单方法二

    使用mod_proxy 这种方法要添加上mod_proxy_http.so 在httpd.conf 中打开httpd-vhost 在 httpd-vhost 里面添加上 <VirtualHost ...

  9. 从源代码上分析ListView的addHeaderView和setAdapter的调用顺序

    ListView想要加入headerview的话,就要通过addHeaderView这种方法,然后想要为ListView设置数据的话,就要调用setAdapter方法了.可是,在调用addHeader ...

  10. R - 变化plot字形,嵌入字体以pdf

    近期使用R绘图遇到两个问题 1. 使用不同的字体 2. 保存 plot 至 pdf 当字体嵌入pdf (embed the font) 使用extrafont和Ghostscript能够解决这两个问题 ...