我想让ASP.NET Core Identity在用户未登录时返回401。我已经在我的方法上添加了[Authorize]
特性,但它返回302而不是401。我尝试了很多建议,包括使用services.Configure
和app.UseCookieAuthentication
将LoginPath
设置为null
或PathString.Empty
,但似乎都没有起作用。
我想让ASP.NET Core Identity在用户未登录时返回401。我已经在我的方法上添加了[Authorize]
特性,但它返回302而不是401。我尝试了很多建议,包括使用services.Configure
和app.UseCookieAuthentication
将LoginPath
设置为null
或PathString.Empty
,但似乎都没有起作用。
截至ASP.NET Core 2.x:
services.ConfigureApplicationCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
如果请求头中包含 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);
}
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);
}
};
});
Source:
对于 asp.net mvc core 请使用此方法替代
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;
};
});
return Task.CompletedTask;
替代 return Task.FromResult<object>(null);
。 - SerjGservices.AddIdentity(…)
或 AddDefaultIdentity(…)
之后。 - Jamie Fservices.AddIdentity
时添加以下内容。services.AddIdentity<ApplicationUser, IdentityRole>(o => {
o.Cookies.ApplicationCookie.AutomaticChallenge = false;
});
WWW-Authenticate
header MUST be provided on 401.If the protected resource request does not include authentication credentials or does not contain an access token that enables access to the protected resource, the resource server MUST include the HTTP "WWW-Authenticate" response header field
- urbanhusky对于使用Identity和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;
};
});
AddIdentity
之后指定ConfigureApplicationCookie
。这是“悲伤”但却是事实。这个SO答案终于给黑暗带来了光明。ApplicationCookie
(但在调用AddIdentity
之前不起作用)1. Startup.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. 帮助器自定义类
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);
}
}
对于我来说,在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;
};
}
);