【问题标题】:How to intercept 401 from Forms Authentication in ASP.NET MVC?如何从 ASP.NET MVC 中的表单身份验证中拦截 401?
【发布时间】:2026-01-05 02:45:01
【问题描述】:

如果用户没有正确的权限,我想生成一个401页面。

用户请求一个 url 并被重定向到登录页面(我在 web.config 中拒绝了所有匿名)。用户登录成功并被重定向到原始 url。但是,经过权限检查,确定用户没有所需的权限,所以我想生成一个 401。但是 Forms Authentication 总是处理 401 并将用户重定向到登录页面。

对我来说,这是不正确的。用户已经认证,只是用户没有适当的授权

在其他场景中,例如在 ajax 或 REST 服务场景中,我绝对不想要登录页面 - 我需要正确的 401 页面。

到目前为止,我已经尝试自定义授权过滤器以返回带有 401 的 ViewResult,但没有奏效。然后我尝试了一个普通的动作过滤器,覆盖了 OnActionExecuting,它也不起作用。

我能够做的是处理 global.asax 中的一个事件,PostRequestHandlerExecute,并检查权限,然后直接写出响应:

if (permissionDenied)
{
    Context.Response.StatusCode = 401;
    Context.Response.Clear();
    Context.Response.Write("Permission Denied");
    Context.Response.Flush();
    Context.Response.Close();
    return;
}

这行得通,但这并不是我真正想要的。 首先,我什至不确定这是否是正确的事件或正在筹备中的地方。 其次,我希望 401 页面有更多的内容。最好,它应该是一个 aspx 页面,其母版页可能与站点的其余部分相同。这样,任何浏览该站点的人都可以看到权限被拒绝但具有相同的外观和感觉等,但 ajax 或服务用户将获得正确的状态代码以进行操作。

知道如何实现吗? 我看过其他有类似要求的帖子,但没有看到我可以使用的解决方案。

不,我不想要 403。

【问题讨论】:

    标签: asp.net asp.net-mvc authorization action-filter


    【解决方案1】:

    我找到了一个可行的解决方案。

    FormsAuthenticationModule

    401 重定向发生在 EndRequest 期间。由于在事件处理期间模块在 global.asax 之前被调用,我们可以在 FormsAuthenticationModule 处理请求之后覆盖状态代码。

    在我的自定义 AuthorizationFilter 中,我将 HttpContext.Items["PermissionDenied"] 设置为 true,然后在我的 global.asax EndRequest 中,我将状态码从 200 翻转到 401。然后我 Server.Transfer 到我的自定义 PermissionDenied 视图。

    我仍然希望 FormsAuthenticationModule 本身已更新以处理这种情况,但我认为这并不太老套,我认为我可以接受它。

    显然,您可以更改发出 global.asax 应该翻转状态代码的信号方式。我只是尝试将状态代码设置为 511 之类的东西,并将其用作条件而不是 HttpContext.Items 并且效果也很好。我猜只要正确的状态码发出来,ASP.NET 引擎就不会在意。

    【讨论】:

      【解决方案2】:
      HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true;
      

      【讨论】:

        【解决方案3】:

        我同意默认行为是错误的,尤其是考虑到 Ajax 请求。我希望在 MVCv3 中看到某种解决方案(祈祷)。

        我知道完成此操作的唯一方法是删除 web.config 的 Authentication 部分,这是 ASP.NET 寻找重定向未经授权的请求的方法。据我所知,您不能禁用此“功能”。如果您有身份验证部分,如果 ASP.NET 遇到401 状态代码,您将被重定向到登录 url。

        但是通过删除它,您会遇到一些其他问题。如果您希望将用户重定向到非 ajax 请求的登录页面,您需要实现自己的 AuthorizeAttribute 并使用自定义设置来确定重定向到的位置。此外,身份验证部分中的任何其他内容也可能必须由您重新实现。在复杂的网站中不是一个非常实用的解决方案。

        我自己没有这样做,我决定返回403。没有返回正确的 HttpCode 很烦人,但它比我迄今为止找到的任何其他解决方案都要好。

        【讨论】:

        • 你是对的 - 我只是将 Reflector 带入 FormsAuthenticationModule 并在 EndRequest 处理中检查 401 和重定向。看起来也没有办法覆盖这种行为。
        • 是的,403 听起来不再那么糟糕了 :)
        【解决方案4】:

        您可能想看这里:ASP.NET MVC Custom Error Handling Application_Error Global.asax?

        此时您应该能够捕获 401 并路由到自定义操作。我们正在为代码中的 404 和其他异常执行此操作,并且运行良好。

        【讨论】:

        • 我不确定您要引导我找到哪个答案。在任何情况下,我都不想重新路由或重定向,因为这样我的响应状态就不会是 401 - 它将类似于 302 后跟 200,如果我从一个 ajax 客户端。
        • Jiho - 抱歉,我没有仔细阅读这个问题。我以为你只是想进行自定义 401 重定向。
        最近更新 更多