401未经授权的就地处理(无重定向)?

时间:2013-12-13 21:55:31

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

问题

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

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

-

背景

我实施了Application_EndRequest() shim来解决由FormsAuthentication引起的AJAX问题。它将所有401 UNAUTHORIZED转换为302 FOUND(即重定向)。但是,这会导致其他问题,因为现在所有 302重定向都转换为401。所以为了解决这个问题,我摆脱了500 SERVER ERROR404 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。 / p>

据我所知,下面的代码代表了我目前唯一依赖FormsAuthentication的地方,如果我不想要401 - &gt; 302处理。

/// <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进行了讨论。

1 个答案:

答案 0 :(得分:12)

检查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();
}

显然,如果您不希望他们接管401状态代码,您可能还想删除web.config中的任何自定义错误页面。