如何在ASP.NET Core中返回401而不是302?

Eri*_*c B 24 c# asp.net-core asp.net-core-identity

当用户未登录时,我试图让ASP.NET Core Identity返回401.我已经[Authorize]为我的方法添加了一个属性,而不是返回401,它返回302.我已经尝试了很多建议但是似乎没什么用,包括services.Configureapp.UseCookieAuthentication设置LoginPathnullPathString.Empty.

Mat*_*kan 45

ASP.NET Core 2.x开始:

services.ConfigureApplicationCookie(options =>
{
    options.Events.OnRedirectToLogin = context =>
    {
        context.Response.StatusCode = 401;    
        return Task.CompletedTask;
    };
});
Run Code Online (Sandbox Code Playgroud)

  • 我相信kroatti的答案应该是公认的答案.如果您希望ajax请求获得401但非ajax请求被重定向,则上述方法将导致问题.根据Mark Perry的回答,您可以添加逻辑来处理它,但是这个逻辑已经内置到具有X-Requested-With:XMLHttpRequest标头的请求的框架中. (3认同)
  • 这工作了。框架中多么令人讨厌的功能。如果我们想要重定向,我们可以指定它... (3认同)
  • 同样,您对services.AddIdentity的调用必须在此之前 (2认同)

小智 15

如果请求标头包含X-Requested-With:XMLHttpRequest,则状态代码将为401而不是302

private static bool IsAjaxRequest(HttpRequest request)
    {
        return string.Equals(request.Query["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal) ||
            string.Equals(request.Headers["X-Requested-With"], "XMLHttpRequest", StringComparison.Ordinal);
    }
Run Code Online (Sandbox Code Playgroud)

请参阅gitHub:https://github.com/aspnet/Security/blob/5de25bb11cfb2bf60d05ea2be36e80d86b38d18b/src/Microsoft.AspNetCore.Authentication.Cookies/Events/CookieAuthenticationEvents.cs#L40-L52

  • 这应该是最直接的答案,而不会损害您的代码库。哎呀,为什么我没有早点找到你。 (2认同)
  • 这不是一个很有帮助的答案,因为它要求调用者注入专有的头值。如何修复处理程序代码以实际接受Accept:标头呢?我的客户端代码(角度)正在发送“ Accept:application / json”,但返回HTML作为无法解析的响应。服务器端代码就是问题所在。 (2认同)

Fra*_*osu 12

对于Asp.net Core 2,请 使用此安装程序

 services.ConfigureApplicationCookie(options =>
        {
            options.LoginPath = new PathString("/Account/Login");
            options.LogoutPath = new PathString("/Account/Logout");

            options.Events.OnRedirectToLogin = context =>
            {
                if (context.Request.Path.StartsWithSegments("/api")
                    && context.Response.StatusCode == StatusCodes.Status200OK)
                {
                    context.Response.Clear();
                    context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                    return Task.CompletedTask;
                }
                context.Response.Redirect(context.RedirectUri);
                return Task.CompletedTask;
            };
        });
Run Code Online (Sandbox Code Playgroud)

  • 使用ASP.NET Core 2.0,您可以使用`return Task.CompletedTask;`而不是`return Task.FromResult <object>(null);` (3认同)
  • 谢谢,这很好用。但是,有没有办法返回 401 和 json (类似于 {authorize: "Failed" }) (2认同)

Mar*_*rry 11

services.Configure<IdentityOptions>(options =>
{
   options.Cookies.ApplicationCookie.LoginPath = new PathString("/");
   options.Cookies.ApplicationCookie.Events = new CookieAuthenticationEvents()
   {
      OnRedirectToLogin = context =>
      {
         if (context.Request.Path.Value.StartsWith("/api"))
         {
            context.Response.Clear();
            context.Response.StatusCode = 401;
            return Task.FromResult(0);
         }
         context.Response.Redirect(context.RedirectUri);
         return Task.FromResult(0);
      }
   };
});
Run Code Online (Sandbox Code Playgroud)

资源:

https://www.illucit.com/blog/2016/04/asp-net-5-identity-302-redirect-vs-401-unauthorized-for-api-ajax-requests/

  • 遗憾的是,这不适用于身份核心2 (4认同)

Eri*_*c B 5

好吧,在深入研究asp.net核心单元测试之后,我终于找到了一个可行的解决方案.您必须在通话中添加以下内容services.AddIdentity

services.AddIdentity<ApplicationUser, IdentityRole>(o => {
    o.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
Run Code Online (Sandbox Code Playgroud)