2013-04-30 56 views
12

在ASP.NET MVC項目中,當您使用[Authorize]裝飾類或方法並且授權失敗時,站點會自動重定向到登錄頁面(使用web中指定的loginUrl的.config)。另外,ASP.NET MVC框架中的某些東西將原始請求的URL作爲ReturnUrl參數傳遞。當使用AuthorizeAttribute時最初設置ReturnUrl參數的內容

什麼是追加此ReturnUrl負責?我在項目模板中找不到任何代碼。我還查看了ASP.NET堆棧source code中的AuthorizeAttribute代碼,但在那裏找不到任何東西。我也嘗試在整個ASP.NET堆棧源代碼中搜索「returnurl」,但找不到任何東西。

我問的原因是我在這個過程中發現了一個錯誤。您可以使用全新的Internet ASP.NET MVC項目來查看此內容。在web.config中將FormsAuth超時設置爲1分鐘,然後登錄。等待一分鐘後嘗試退出。這將重定向到登錄頁面/帳戶/註銷的RETURNURL,這導致404在登錄後,我解決這個現在我自己AuthorizeAttribute工作了:

public class MyAuthorizeAttribute : AuthorizeAttribute 
{ 
    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     base.OnAuthorization(filterContext); 

     if (filterContext.Result is HttpUnauthorizedResult) 
     { 
      string returnUrl = null; 
      if (filterContext.HttpContext.Request.HttpMethod.Equals("GET", System.StringComparison.CurrentCultureIgnoreCase)) 
       returnUrl = filterContext.HttpContext.Request.RawUrl; 

      filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary() 
      { 
       { "client", filterContext.RouteData.Values[ "client" ] }, 
       { "controller", "Account" }, 
       { "action", "Login" }, 
       { "ReturnUrl", returnUrl } 
      }); 
     } 
    } 
} 

不過,我想看看源代碼,看看我能否找出這個bug存在的原因,如果它確實是一個bug。

+0

我認爲這是表單身份驗證的一部分,不僅僅是MVC特有的。返回URL也存在於WebForm中 – Devesh 2013-04-30 17:52:17

+0

它可能是 - 我認爲它與MVC有關,因爲AuthorizationAttribute位於MVC命名空間中,並且覆蓋OnAuthorization(如上所示)似乎解決了該問題。 – 2013-04-30 18:11:16

+0

http://msdn.microsoft.com/en-us/library/ff647070.aspx,可能會幫助你 – Devesh 2013-04-30 18:13:05

回答

10

returnUrl querystring參數被添加到重定向到System.Web.dll程序集的FormsAuthentication類中的登錄頁面。 FormsAuthenticion.RedirectToLoginPage方法重載最終會調用內部方法GetLoginPage。 「ReturnUrl」變量和LoginUrl的名稱都可以通過web.config設置覆蓋。

當默認的AuthorizeAttribute遇到一個未經授權的請求時,它只是返回一個HttpUnauthorizedResult,它僅僅是一個狀態代碼爲401的HttpStatusCodeResult的包裝。FormsAuthenticationModule在幕後開始並完成剩下的工作。 MVC和這些基類之間沒有直接的交互,除非你直接調用FormsAuthentication類的靜態方法。

當您想覆蓋此行爲時,您的解決方案是標準解決方案。

的GetLoginPage方法做的工作如下:

internal static string GetLoginPage(string extraQueryString, bool reuseReturnUrl) 
{ 
    HttpContext current = HttpContext.Current; 
    string loginUrl = FormsAuthentication.LoginUrl; 
    if (loginUrl.IndexOf('?') >= 0) 
    { 
     loginUrl = FormsAuthentication.RemoveQueryStringVariableFromUrl(loginUrl, FormsAuthentication.ReturnUrlVar); 
    } 
    int num = loginUrl.IndexOf('?'); 
    if (num >= 0) 
    { 
     if (num < loginUrl.Length - 1) 
     { 
      loginUrl = string.Concat(loginUrl, "&"); 
     } 
    } 
    else 
    { 
     loginUrl = string.Concat(loginUrl, "?"); 
    } 
    string str = null; 
    if (reuseReturnUrl) 
    { 
     str = HttpUtility.UrlEncode(FormsAuthentication.GetReturnUrl(false), current.Request.QueryStringEncoding); 
    } 
    if (str == null) 
    { 
     str = HttpUtility.UrlEncode(current.Request.RawUrl, current.Request.ContentEncoding); 
    } 
    loginUrl = string.Concat(loginUrl, FormsAuthentication.ReturnUrlVar, "=", str); 
    if (!string.IsNullOrEmpty(extraQueryString)) 
    { 
     loginUrl = string.Concat(loginUrl, "&", extraQueryString); 
    } 
    return loginUrl; 
}