37

我试图让 ASP.NET Core Identity 在用户未登录时返回 401。我在[Authorize]我的方法中添加了一个属性,而不是返回 401,而是返回 302。我尝试了很多建议,但是似乎没有任何效果,包括services.Configureapp.UseCookieAuthentication设置LoginPathnullor PathString.Empty

4

8 回答 8

63

ASP.NET Core 2.x开始:

services.ConfigureApplicationCookie(options =>
{
    options.Events.OnRedirectToLogin = context =>
    {
        context.Response.StatusCode = 401;    
        return Task.CompletedTask;
    };
});
于 2017-07-24T03:00:57.257 回答
24

如果请求头包含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);
    }

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

于 2018-02-13T16:58:51.153 回答
15

对于 asp.net mvc 核心 使用这个代替

 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;
            };
        });
于 2017-11-11T17:09:26.153 回答
14
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);
      }
   };
});

来源:

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

于 2017-01-23T15:39:13.983 回答
5

好吧,在asp.net 核心单元测试中挖掘之后,我终于找到了一个可行的解决方案。您必须将以下内容添加到您的呼叫中services.AddIdentity

services.AddIdentity<ApplicationUser, IdentityRole>(o => {
    o.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
于 2016-08-06T06:09:01.597 回答
4

对于使用带有 Cookie 身份验证的身份的ASP.NET Core 3.x(预览版),这就是诀窍:

services.AddIdentity<ApplicationUser, IdentityRole>()
    .AddEntityFrameworkStores<IdentityContext>()
    .AddDefaultTokenProviders()
    .AddRoles<IdentityRole>();

services.ConfigureApplicationCookie(options =>
{
    options.Events.OnRedirectToLogin = context =>
    {
        context.Response.Headers["Location"] = context.RedirectUri;
        context.Response.StatusCode = 401;
        return Task.CompletedTask;
    };
});

这是我们随处可见的不同变体。但是,这里的要点是ConfigureApplicationCookie必须在AFTER 之后 AddIdentity指定。这很“悲伤”,但却是真实的。这个SO 答案终于在黑暗中带来了光明。

我已经摸索了一天多,尝试了许多不同的变化:

  • 覆盖 Authorize 属性(不再需要在 3.x 中覆盖)
  • 使用 Cookie 指定 options.Cookie.EventType(运行时错误)
  • options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme(据说JWT承载不会重定向到登录页面)
  • 当然,配置ApplicationCookie(但在调用AddIdentitywhich 之前不起作用。

那一切都没有奏效。但是有了上面的答案,我终于得到了 401 Unauthorized 的返回(顺便说一下应该是Unauthenticated

于 2019-08-01T11:53:57.183 回答
1

接下来,我将之前的答案合并为以下内容:

1. 启动.cs

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

            options.Events.OnRedirectToAccessDenied = context =>
            {
                if (wlt_AjaxHelpers.IsAjaxRequest(context.Request))
                {
                    context.Response.Clear();
                    context.Response.StatusCode = StatusCodes.Status401Unauthorized;
                    return Task.CompletedTask;
                }
                context.Response.Redirect(context.RedirectUri);
                return Task.CompletedTask;
            };
        });

2. Helper自定义类

public static class wlt_AjaxHelpers
     {

        public 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);
        }

    }
于 2019-09-30T07:49:44.413 回答
0

对我来说,在 ASP.NET Core 2.2.0 上只有这行得通:

services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
    .AddCookie(
        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;
            };
        }
    );
于 2019-05-17T11:10:28.237 回答