我有一个 ASP.NET 核心网站,对大多数页面使用 cookie 身份验证。对于这些页面,需要为未经授权的客户端提供 302 重定向的默认服务器响应。但是,该站点也接受 API 请求;他们使用 API 密钥,不使用 cookie。
理想情况下,我想完全关闭 API URL 的 cookie 处理,但至少,我需要确保如果 API 客户端未经授权,服务器不会响应 302 重定向。
重定向事件处理程序替换为仅在路径不是 API 时才使用默认行为的处理程序。在 Startup.ConfigureServices
中,添加以下内容:
services.ConfigureApplicationCookie(options => {
options.Events.OnRedirectToAccessDenied = ReplaceRedirector(HttpStatusCode.Forbidden, options.Events.OnRedirectToAccessDenied);
options.Events.OnRedirectToLogin = ReplaceRedirector(HttpStatusCode.Unauthorized, options.Events.OnRedirectToLogin);
});
使用此帮助程序方法替换重定向方法:
static Func<RedirectContext<CookieAuthenticationOptions>, Task> ReplaceRedirector(HttpStatusCode statusCode, Func<RedirectContext<CookieAuthenticationOptions>, Task> existingRedirector) =>
context => {
if (context.Request.Path.StartsWithSegments("/api")) {
context.Response.StatusCode = (int)statusCode;
return Task.CompletedTask;
}
return existingRedirector(context);
};
完成此操作后,API 控制器方法可以调用Unauthorized()
和Forbid()
,而不会导致重定向。
更新:以上适用于 ASP.NET Core 2。ASP.NET 核心 1 的代码是不同的。
对于 .net core 2.x,这里有一个修复(基于 Edward 的回答):
services.ConfigureApplicationCookie(options =>
{
options.Events = new CookieAuthenticationEvents
{
OnRedirectToAccessDenied = ReplaceRedirector(HttpStatusCode.Forbidden, context => options.Events.RedirectToAccessDenied(context)),
OnRedirectToLogin = ReplaceRedirector(HttpStatusCode.Unauthorized, context => options.Events.RedirectToLogin(context))
};
});
其中ReplaceRedirector
:
Func<RedirectContext<CookieAuthenticationOptions>, Task> ReplaceRedirector(HttpStatusCode statusCode, Func<RedirectContext<CookieAuthenticationOptions>, Task> existingRedirector) =>
context =>
{
if (context.Request.Path.StartsWithSegments("/api"))
{
context.Response.StatusCode = (int)statusCode;
return Task.CompletedTask;
}
return existingRedirector(context);
};
其他简单方法
.AddCookie(options =>
{
options.AccessDeniedPath = "/Home/401";
options.Events = new CookieAuthenticationEvents
{
OnRedirectToAccessDenied = context =>
{
if (context.Request.Path.StartsWithSegments("/api"))
{
context.Response.StatusCode = (int)(HttpStatusCode.Unauthorized);
}
return Task.CompletedTask;
},
};
})