在 ASP.NET Core 中抑制 API URL 的重定向

Suppress redirect on API URLs in ASP.NET Core

我有一个 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的。code for ASP.NET Core 1不同。

对于 .net 核心 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;
                    },
                };
            })