【问题标题】:HttpStatusCodeResult(401) returns “200 OK”HttpStatusCodeResult(401) 返回“200 OK”
【发布时间】:2017-05-24 04:19:10
【问题描述】:

使用 ASP.NET MVC 5,我想为不同的场景返回适当的 HTTP 状态代码(401 表示用户未通过身份验证,403 表示用户无权访问某些资源等),然后在 jQuery 中处理它们。

但问题是,当我尝试返回 401 时,它总是返回“200:OK”。 MVC 5 RC1 给出的是“302: Found”而不是 401,所以我可以使用解决方法 (HttpStatusCodeResult(401) returns "302 Found")。 但现在我从 MVC 5 RC1 迁移到 MVC 5,这种行为发生了变化。现在它总是“200:OK”。所以我的解决方法是没用的,当然我不能用其他任何东西替换 200。

public ActionResult My()
{
    if (User.Identity.IsAuthenticated == false)
    {
        return new HttpStatusCodeResult(401, "User is not authenticated."); 
            // Returns "200: OK"
    }

   // ... other code ...
}

如何解决?

【问题讨论】:

  • 向我们展示一些您使用 401 的示例代码,以便我们为您提供帮助。没有代码 == 没有帮助。
  • 你不应该明确地检查User.Identity.IsAuthenticated。 ASP.NET MVC 中的身份验证通常使用属性完成;您应该将 Authorize 属性应用于您的方法。
  • 你怎么知道它返回 200?你在使用提琴手或类似的东西吗?我在机器上的 VS2013 中创建了一个新的 MVC 5 项目,将return new HttpStatusCodeResult(401, "User is not authenticated."); 粘贴到一个动作中,我在提琴手中看到了 302,正如我所期望的那样。你有不同的结果吗?
  • 我也有同样的问题,没有找到任何解决方案。我返回新的 HttpUnauthorizedResult();从 HandleUnauthorizedRequest 方法和浏览器提琴手它接收它作为 200 OK。我知道上周这对我有用,我本周做了完整的 Windows 7 更新,但这对我停止了工作。
  • 您使用的是什么 OWIN 中间件(如果有)?身份验证中间件拦截 401 并重写对质询的响应是很常见的。我怀疑这种重写是您问题的根本原因。

标签: c# asp.net asp.net-mvc http-status-codes asp.net-mvc-5


【解决方案1】:

MVC 5+ 管道修改 401 响应代码。

选项 1 使用 .net 4.5

您可以将HttpContext.Response.SuppressFormsAuthenticationRedirect 设置为true。

例如在您的自定义 AuthoriseAttribute.cs

    protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext)
    {
        if (filterContext.HttpContext.Request.IsAjaxRequest())
        {
            filterContext.Result = new JsonResult
            {
                Data = "_Logon_",
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.Unauthorized; 
            filterContext.HttpContext.Response.SuppressFormsAuthenticationRedirect = true;
        }

选项 2。如果不使用 .net 4.5

  public class SuppressFormsAuthenticationRedirectModule : IHttpModule
{
    private static readonly object SuppressAuthenticationKey = new object();

    public static void Register()
    {
        DynamicModuleUtility.RegisterModule(
            typeof(SuppressFormsAuthenticationRedirectModule));
    }

    public static void SuppressAuthenticationRedirect(HttpContext context)
    {
        context.Items[SuppressAuthenticationKey] = true;
    }

    public static void SuppressAuthenticationRedirect(HttpContextBase context)
    {
        context.Items[SuppressAuthenticationKey] = true;
    }

    public void Init(HttpApplication context)
    {
        context.PostReleaseRequestState += OnPostReleaseRequestState;
        context.EndRequest += OnEndRequest;
    }

    public void Dispose()
    {
    }

    private void OnPostReleaseRequestState(object source, EventArgs args)
    {
        var context = (HttpApplication)source;
        var response = context.Response;
        var request = context.Request;

        if (response.StatusCode == 401 && request.Headers["X-Requested-With"] == "XMLHttpRequest")
        {
            SuppressAuthenticationRedirect(context.Context);
        }
    }

    private void OnEndRequest(object source, EventArgs args)
    {
        var context = (HttpApplication)source;
        var response = context.Response;

        if (context.Context.Items.Contains(SuppressAuthenticationKey))
        {
            response.TrySkipIisCustomErrors = true;
            response.ClearContent();
            response.StatusCode = 401;
            response.RedirectLocation = null;
        }
    }
}

在 web.config 中

 <modules>
  <add name="SuppressFormsAuthenticationRedirectModule" type="SuppressFormsAuthenticationRedirectModule"/>
</modules>

See here for more info

【讨论】:

    【解决方案2】:

    问题的解决方法可以在http://kevin-junghans.blogspot.in/2013/12/returning-401-http-status-code-on.html找到

    您需要像这样修改您的Startup 类:

    public partial class Startup
    {
    private static bool IsAjaxRequest(IOwinRequest request)
    {
        IReadableStringCollection query = request.Query;
        if ((query != null) && (query["X-Requested-With"] == "XMLHttpRequest"))
        {
            return true;
        }
        IHeaderDictionary headers = request.Headers;
        return ((headers != null) && (headers["X-Requested-With"] == "XMLHttpRequest"));
    }
    
    // For more information on configuring authentication, please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        // Enable the application to use a cookie to store information for the signed in user
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
            LoginPath = new PathString("/Account/Login"),
            Provider = new CookieAuthenticationProvider
            {
                OnApplyRedirect = ctx =>
                {
                    if (!IsAjaxRequest(ctx.Request))
                    {
                        ctx.Response.Redirect(ctx.RedirectUri);
                    }
                }
            }
        });
        // Use a cookie to temporarily store information about a user logging in with a third party login provider
        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
    
    }
    

    }

    【讨论】:

    • 链接失效了。该网站仍然存在,但帖子无法访问
    【解决方案3】:

    我使用返回 404 的模拟代码。您的代码可能是:

    public ActionResult My()
    {
      if (User.Identity.IsAuthenticated == false)
      {
        return new HttpUnauthorizedResult();
      }
      // ... other code ...
    }
    

    【讨论】:

      【解决方案4】:

      在 Statup.cs 中,我必须将 AutomaticChallenge 设置为 false。一旦我这样做了,它就停止了 URL 重定向(导致 200 状态)并给了我想要的 401 状态。

      public void ConfigureServices(IServiceCollection services)
      {
          services.AddIdentity<ApplicationUser, ApplicationRole>(options =>
          {
             options.Cookies.ApplicationCookie.AutomaticChallenge = false;  //<@@@@@@@
             //...
          })
          .AddEntityFrameworkStores<ApplicationDbContext, int>()
          .AddDefaultTokenProviders();
      }
      

      如果你设置了一些cookie中间件:

      public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IAntiforgery antiforgery)
      {
         app.UseCookieAuthentication(new CookieAuthenticationOptions()
      
          {
              AuthenticationScheme = "__auth__",
              LoginPath = "/account/login",
              AccessDeniedPath = "/account/forbidden",
              AutomaticAuthenticate = true,
              AutomaticChallenge = false  //<@@@@@@@
          });
      }
      

      【讨论】:

        【解决方案5】:

        对于身份中间件,可以通过在 Startup.Auth.cs 中删除 LoginPath 选项来禁用重定向:

           public void ConfigureAuth(IAppBuilder app)
            {
                app.UseCookieAuthentication(new CookieAuthenticationOptions
                {
                    ...
                    LoginPath = new PathString("/Account/Login"), // Remove this line
                });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2022-10-04
          • 2021-07-11
          • 2011-03-25
          • 2019-10-29
          • 1970-01-01
          • 1970-01-01
          • 2011-10-27
          相关资源
          最近更新 更多