在ASP.NET MVC项目中,当您使用[授权]和授权进行装饰类或方法失败时,站点会自动重定向到登录页面(使用web.config中指定的loginUrl).另外,ASP.NET MVC框架中的东西将原始请求的URL作为ReturnUrl参数传递.
什么负责追加这个ReturnUrl?我在项目模板中找不到任何代码.我还看看了ASP.NET stack source code中AuthorizeAttribute的代码,但是找不到任何东西.我还尝试搜索整个ASP.NET堆栈源代码“returnurl”,但找不到任何东西.
我问的原因是我在这个过程中发现了一个错误.您可以使用全新的Internet ASP.NET MVC项目来看到这一点.在Web.config中将FormsAuth超时设置为1分钟,然后登录.等待一分钟,然后尝试退出.这将重定向到具有ReturnUrl / account / logoff的登录页面,这在登录之后导致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.
解决方法
将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; }