【问题标题】:Suppress redirect on API URLs in ASP.NET Core禁止在 ASP.NET Core 中对 API URL 进行重定向
【发布时间】:2017-06-21 04:08:27
【问题描述】:

我有一个 ASP.NET Core 站点,它对大多数页面使用 cookie 身份验证。对于这些页面,需要为未经授权的客户端提供 302 重定向的默认服务器响应。但是,该站点也接受 API 请求;他们使用 API 密钥,不使用 cookie。

理想情况下,我想完全关闭 API URL 的 cookie 处理,但至少,我需要确保如果 API 客户端未经授权,服务器不会以 302 重定向响应。

【问题讨论】:

    标签: authentication cookies asp.net-core asp.net-identity-2 http-redirect


    【解决方案1】:

    仅当路径不是 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 不同。

    【讨论】:

    • +1。应该注意的是,services.ConfigureApplicationCookie() 调用应该在 设置您的身份验证的调用之后(在我的情况下为 services.AddIdentity()),否则这些设置将被覆盖
    • 与 spa 一起使用时,这似乎是一种非常干净的方式。
    • 我尝试在我的 .NET Core 3.0 Web API 项目中实现您的解决方案,但没有成功。似乎从未调用过传递给ConfigureApplicationCookie 的动作委托参数;我在它的第一行设置了一个断点,但它从未被命中。当我的测试 API 的控制器调用 Forbid 时,我的测试客户端应用程序不断收到 HTTP 状态代码 500 而不是 403。有什么想法吗?
    • .NET Core 3.1 也有同样的问题。这段代码似乎根本不起作用。有什么想法吗?
    • 这是一个绝妙的解决方案,可以确认它适用于 .NET Core 5.0
    【解决方案2】:

    对于 .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);
    };
    

    【讨论】:

    • 我更新了我的答案以包含 ASP.NET Core 2。在我的更新中,我没有替换 Events,而只是设置了它的相关属性。
    【解决方案3】:

    其他简单的方法

     .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;
                        },
                    };
                })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-24
      • 1970-01-01
      • 2019-05-24
      • 1970-01-01
      • 1970-01-01
      • 2017-02-07
      相关资源
      最近更新 更多