在ASP.NET MVC项目中,当您使用[Authorize]修饰类或方法并且授权失败时,该站点会自动重定向到登录页面(使用web.config中指定的loginUrl)。此外,ASP.NET MVC框架中的某些内容将原始请求的URL作为ReturnUrl参数传递。
有什么责任追加这个ReturnUrl?我在项目模板中找不到任何代码。我还看了一下ASP.NET堆栈source code中的AuthorizeAttribute代码,但在那里找不到任何东西。我也尝试在整个ASP.NET堆栈源代码中搜索“returnurl”但找不到任何东西。
我问的原因是我在这个过程中发现了一个错误。您可以通过全新的Internet ASP.NET MVC项目看到这一点。在web.config中将FormsAuth超时设置为1分钟,然后登录。等待一分钟后尝试注销。这将重定向到具有/ account / logoff的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 :(得分:10)
returnUrl querystring参数被添加到重定向到System.Web.dll程序集中FormsAuthentication类内的登录页面。 FormsAuthenticion.RedirectToLoginPage方法重载最终调用内部方法GetLoginPage。 “ReturnUrl”变量的名称和LoginUrl都可以通过web.config设置覆盖。
当默认的AuthorizeAttribute遇到未经授权的请求时,它只返回一个HttpUnauthorizedResult,它只是HttpStatusCodeResult的一个包装器,状态代码为401.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;
}
答案 1 :(得分:0)
试试这个
returnUrl = filterContext.HttpContext.Request.Url.GetComponents(UriComponents.PathAndQuery, UriFormat.SafeUnescaped) ;
我在Generate a return Url with a custom AuthorizeAttribute
找到了它这适合我。