【问题标题】:In-place handling (no redirect) of 401 unauthorized?未经授权的 401 就地处理(无重定向)?
【发布时间】:2013-12-13 21:55:30
【问题描述】:

问题

什么是直接返回 401 和登录页面的简单方法,避免 302 重定向,当IAuthorizationFilter 在 IIS 7.0 上的 ASP.NET MVC 5 应用程序中失败时,我必须实现哪些基础架构这份工作?

可能的替代问题:这是一个坏主意吗?

-

背景

我实现了Application_EndRequest() shim 来解决FormsAuthentication 引起的AJAX 问题。它将所有401 UNAUTHORIZED 转换为302 FOUND(即重定向)。但是,这会导致其他问题,因为现在 所有 302 重定向都转换为 401。所以为了解决这个问题,我去掉了500 SERVER ERROR404 NOT FOUND 的重定向,我认为我仍然错过了一些...

也许我对此进行了过度设计,但是在这个练习之后,首先返回 302 来代替 401 似乎是不正确的。解决了一个问题,创造了新的问题。我认为技术上理想的答案是就地处理 401。然后服务器会发送一个诚实的状态码,无论是否 AJAX,如果 AJAX 客户端收到登录 HTML 也没什么大不了的。

-

我的进步

在没有 FormsAuthentication 的情况下使用 FormsAuthentication cookie

我尝试了一种方法,使用:

<httpErrors errorMode="Custom" existingResponse="Replace">
    <error statusCode="401" responseMode="ExecuteURL" path="/Account/AuthReq" />
</httpErrors>

但是,为了完成这项工作,我必须从 Web.config 中提取 FormsAuthentication,当我提取表单身份验证时,我的自定义 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。我尚未调查此更改是否与相当新的基于声明的票证或 MVC5 中非常新的 AuthenticationFilter 相关。

使用 AppHarbor 的 .NET 开放式身份验证库

虽然我不确定这是否适用于我的场景,但此处对类似主题的一些答案表明无法禁用 FormsAuthentication 的 302 重定向操作。然而,似乎很清楚 ASP.NET 中没有包含替代的身份验证机制。

AppHarbor 已向GitHub 发布了一个替换库,并在their blog 进行了讨论。

【问题讨论】:

    标签: asp.net asp.net-mvc authentication forms-authentication authorize-attribute


    【解决方案1】:

    检查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",
            };
        }
    }
    

    可用于装饰受保护的控制器/操作:

    [MyAuthorize]
    public ActionResult Admin()
    {
        return View();
    }
    

    显然,如果您不希望它们接管,您可能还希望摆脱 web.config 中针对 401 状态代码的任何自定义错误页面。

    【讨论】:

    • 太棒了。我已经有一个自定义授权。谢谢达林。无论如何,我宁愿在此处定义登录操作的路径,而不是在 Web.config 的 httpErrors 部分,因为后者不接受项目相对路径。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-12-23
    • 2020-10-30
    • 1970-01-01
    • 2013-09-11
    • 2012-11-01
    • 2020-04-25
    • 1970-01-01
    相关资源
    最近更新 更多