问题
当 IIS 7.0 上的 ASP.NET MVC 5 应用程序中的 IAuthorizationFilter
失败时,直接返回 401 和登录页面的简单方法是什么,避免 302 重定向?
可能的替代问题:这是一个坏主意吗?
——
背景
我实现了 Application_EndRequest()
shim 来解决由 FormsAuthentication
引起的 AJAX 问题。它将所有 401 UNAUTHORIZED
转换为 302 FOUND
(即重定向)。但是,这会导致其他问题,因为现在所有 302 重定向都转换为 401。所以为了解决这个问题,我去掉了 500 SERVER ERROR
和 404 NOT FOUND
的重定向,我认为还有一些我错过了......
也许我对此进行了过度设计,但是在此练习之后,首先为 401 返回 302 似乎是不正确的。解决了一个问题,创造了新的问题。我认为技术上理想的答案是就地处理 401。然后服务器发送一个诚实的状态代码,无论 AJAX 与否,如果 AJAX 客户端接收到登录 HTML,这没什么大不了的。
——
我的进步
在没有 FormsAuthentication 的情况下使用 FormsAuthentication cookie
我尝试了一种方法,使用:
<httpErrors errorMode="Custom" existingResponse="Replace">
<error statusCode="401" responseMode="ExecuteURL" path="/Account/AuthReq" />
</httpErrors>
但是,为了完成这项工作,我必须从
FormsAuthentication
中提取 Web.config
,并且当我提取表单例份验证时,我的自定义 AuthorizeAttribute
停止运行。我认为我实际使用的 FormsAuthentication
代码很少,但我有点害怕摆脱它,因为我不想将自己的无知应用于管理安全身份验证 cookie。据我所知,如果我不想要 401 -> 302 处理,下面的代码代表了我目前唯一依赖
FormsAuthentication
的地方。/// <summary>
/// Stores this SessionIdentity in the Forms Authentication token for use next request
/// </summary>
public void Write(HttpContext httpContext) {
httpContext.Response.AppendCookie(FormsAuthentication.GetAuthCookie(serialize(), false));
}
/// <summary>
/// Constructs a SessionIdentity from the Forms Authentication token
/// </summary>
public static SessionIdentity Read(HttpContext httpContext) {
IIdentity identity = httpContext.User.Identity;
return identity.IsAuthenticated
? deserialize(identity.Name)
: Unauthenticated;
}
/// <summary>
/// Removes the SessionIdentity Forms Authentication token for the next request
/// </summary>
public static void Clear(HttpContext httpContext) {
var clearAuthCookie = new HttpCookie(FormsAuthentication.FormsCookieName, "");
clearAuthCookie.Expires = DateTime.Now.AddYears(-1);
httpContext.Response.Cookies.Add(clearAuthCookie);
}
似乎我可以避免对 Web.Config 中 FormsAuthentication 的依赖,并且仍然能够使用 OEM 加密票证,只需利用
FormsAuthentication.Decrypt()
而不是我上面所做的 HttpContext.User.Identity
。我尚未调查此更改是否与全新的基于 Claims 的票证或 MVC5 中全新的 AuthenticationFilter 相关。使用 AppHarbor 的 .NET 开放身份验证库
尽管我不确定这对我的场景是否正确,但对此处类似主题的一些答案表明无法禁用 FormsAuthentication 的 302 重定向操作。然而,很明显 ASP.NET 中没有包含替代身份验证机制。
AppHarbor 发布了 GitHub 的替代库,并在 their blog 上进行了讨论。
最佳答案
检查 SuppressFormsAuthenticationRedirect
属性。
然后编写自定义 Authorize 属性:
public class MyAuthorizeAttribute: AuthorizeAttribute
{
protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
{
filterContext.HttpContext.Response.StatusCode = 401;
filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
filterContext.Result = new ViewResult
{
ViewName = "~/Views/Account/Login.cshtml",
};
}
}
可用于装饰 protected Controller / Action :
[MyAuthorize]
public ActionResult Admin()
{
return View();
}
显然,如果您不想让 401 状态代码接管,您可能还想删除 web.config 中的任何自定义错误页面。
关于asp.net - 401 未经授权的就地处理(无重定向)?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/20576697/