当前位置: 移动技术网 > IT编程>开发语言>.net > [ASP.NET]更简单的方法:FormsAuthentication登录ReturnUrl使用绝对路径

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

2018年02月11日  | 移动技术网IT编程  | 我要评论

wayos软路由,苏永康最好听的歌,五星级酒店大涨价

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

 

问题场景

 

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

 

<authentication mode="Forms">

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

</authentication>

当我们访问一个需要登录后才能访问的URL时,比如:https://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("https://" + 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>

 

 

 

如对本文有疑问,请在下面进行留言讨论,广大热心网友会与你互动!! 点击进行留言回复

相关文章:

验证码:
移动技术网