将我的ASP.NET Core项目升级到2.0后,尝试访问受保护的端点不再返回401,而是重定向到(不存在的)端点以尝试让用户进行身份验证。
所需的行为是应用程序只返回401.以前我会在配置身份验证时设置AutomaticChallenge = false
,但根据this article,设置不再相关(实际上它不是已经存在了。)
我的身份验证配置如下:
Startup.cs.ConfigureServices():
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(o =>
{
o.Cookie.Name = options.CookieName;
o.Cookie.Domain = options.CookieDomain;
o.SlidingExpiration = true;
o.ExpireTimeSpan = options.CookieLifetime;
o.TicketDataFormat = ticketFormat;
o.CookieManager = new CustomChunkingCookieManager();
});
配置():
app.UseAuthentication();
如何禁用自动质询,以便在用户未经过身份验证时应用程序返回401?
答案 0 :(得分:24)
正如其他一些答案所指出的那样,不再有使用cookie身份验证关闭自动质询的设置。解决方案是覆盖OnRedirectToLogin
:
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
.AddCookie(options =>
{
options.Events.OnRedirectToLogin = context =>
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
答案 1 :(得分:20)
经过一些研究,我发现我们可以通过下面的方法处理这个问题:
我们可以添加Identity和JWT两种身份验证方案;并使用身份方案进行身份验证并使用JWT模式进行质询,JWT在挑战时不会重定向到任何登录路由。
services.AddIdentity<ApplicationUser, IdentityRole>().AddEntityFrameworkStores<ApplicationDbContext>();
services.AddAuthentication((cfg =>
{
cfg.DefaultScheme = IdentityConstants.ApplicationScheme;
cfg.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})).AddJwtBearer();
答案 2 :(得分:4)
根据this文章:
在1.x中, AutomaticAuthenticate 和 AutomaticChallenge 属性旨在在单个身份验证方案上设置。没有好办法来实施这一点。
在2.0中,这两个属性已作为单个 AuthenticationOptions 实例上的标记删除,并已移至基本AuthenticationOptions类中。可以在Startup.cs的 ConfigureServices 方法中的 AddAuthentication 方法调用中配置属性
services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme);
或者,使用AddAuthentication方法的重载版本来设置多个属性。在以下重载方法示例中,默认方案设置为CookieAuthenticationDefaults.AuthenticationScheme。也可以在您的个人 [授权] 属性或授权政策中指定身份验证方案。
services.AddAuthentication(options => {
options.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
});
如果满足下列条件之一,则在2.0中定义默认方案:
此规则的一个例外是 AddIdentity 方法。此方法为您添加cookie,并将默认的身份验证和质询方案设置为应用程序cookie IdentityConstants.ApplicationScheme 。此外,它还将默认登录方案设置为外部cookie IdentityConstants.ExternalScheme 。
希望这对你有所帮助。
答案 3 :(得分:4)
与@Serverin类似,设置Application Cookie的OnRedirectToLogin工作,但必须在startup.cs中的services.AddIdentity之后的语句中完成:ConfigureServices:
services.ConfigureApplicationCookie(options => {
options.Events.OnRedirectToLogin = context => {
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
return Task.CompletedTask;
};
});
答案 4 :(得分:3)
这是CookieAuthenticationEvents.OnRedirectToLogin的源代码:
public Func<RedirectContext<CookieAuthenticationOptions>, Task> OnRedirectToLogin { get; set; } = context =>
{
if (IsAjaxRequest(context.Request))
{
context.Response.Headers["Location"] = context.RedirectUri;
context.Response.StatusCode = 401;
}
else
{
context.Response.Redirect(context.RedirectUri);
}
return Task.CompletedTask;
};
您可以添加&#34; X-Requested-With:XMLHttpRequest&#34;从客户端进行API调用时,请求标头。
答案 5 :(得分:1)
另一种方法(对DI /测试更友好)是使用AuthenticationSchemeOptions.EventsType
(另一种答案points at it here)。这将使您能够将其他组件拉入解决过程。
这是一个包括注册和解析的示例,该示例停止默认的重定向以登录未经身份验证的请求,而仅返回一个硬401
。它还有一个插槽,用于存放可能需要了解未经身份验证的请求的任何其他依赖项。
在Startup.cs
中:
services
.AddAuthentication("MyAuthScheme")
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, options =>
{
options.EventsType = typeof(MyEventsWrapper);
};
...
services.AddTransient<MyEventsWrapper>();
services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
然后,在MyEventsWrapper.cs
中:
public class MyEventsWrapper : CookieAuthenticationEvents
{
private readonly IHttpContextAccessor _accessor;
private readonly IDependency _otherDependency;
public MyEventsWrapper(IHttpContextAccessor accessor,
IDependency otherDependency)
{
_accessor = accessor;
_otherDependency = otherDependency;
}
public override async Task RedirectToLogin(RedirectContext<CookieAuthenticationOptions> context)
{
context.Response.Headers.Remove("Location");
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
await _otherDependency.Cleanup(_accessor.HttpContext);
}
}
答案 6 :(得分:1)
我发现在大多数情况下,解决方案是覆盖
OnRedirectToLogin
但是在我的应用程序中,我使用了多种身份验证策略,而Fill
的覆盖对我而言无效。在我的情况下,解决方案是添加一个简单的中间件来重定向传入的请求。
OnRedirectToLogin
答案 7 :(得分:0)
我不确定如何生成401错误,但是如果您使用:
o.AccessDeniedPath = "{path to invalid}";
这将允许您在挑战失败时重定向到某个地方。