ASP.Net Core - API 身份验证错误时没有重定向

2024-01-10

在我的 ASP.NET Core 项目中,我有一些具有 jwt 授权的 API 控制器,如下所示:

[Route("api/v1/[controller]")]
public class MyController : Controller
{
  [HttpGet("[action]")]
  [Authorize(Policy = MyPolicy)]
  public JsonResult FetchAll()
  {
  }
}

当访问操作 FetchAll() 的授权失败时,我希望 HttpStatusCode.Forbidden 作为响应。相反,Mvc 会重新路由到 Account/Login?ReturnUrl=[...]

我尝试捕获重定向事件并返回禁止/未经授权覆盖 Cookie 事件,但无济于事:

  app.UseIdentity();

  var tokenValidationParameters = new TokenValidationParameters
  {
    ValidateIssuerSigningKey = true,
    IssuerSigningKey = TokenController.DummyKey,
    ValidateIssuer = false,
    ValidateAudience = false,
    ValidateLifetime = true,
    ClockSkew = TimeSpan.FromMinutes(0)
  };
  app.UseJwtBearerAuthentication(new JwtBearerOptions
  {
    AutomaticAuthenticate = true,
    AutomaticChallenge = true,
    TokenValidationParameters = tokenValidationParameters,
  });

  app.UseCookieAuthentication(new CookieAuthenticationOptions()
  {
    AutomaticAuthenticate = false,
    AutomaticChallenge = false,
    AuthenticationScheme = "BsCookie",
    CookieName = "access_token",
    TicketDataFormat = new CustomJwtDataFormat(SecurityAlgorithms.HmacSha256, tokenValidationParameters),
    Events = new CookieAuthenticationEvents
    {
      OnRedirectToLogin = context =>
      {
        if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.OK)
          context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
        else
          context.Response.Redirect(context.RedirectUri);
        return Task.FromResult(0);
      },

      OnRedirectToAccessDenied = context =>
      {
        if (context.Request.Path.StartsWithSegments("/api") && context.Response.StatusCode == (int)HttpStatusCode.OK)
          context.Response.StatusCode = (int)HttpStatusCode.Forbidden;
        else
          context.Response.Redirect(context.RedirectUri);
        return Task.FromResult(0);
      }
    },
  });

这两个事件都不会被调用,并且 Visual Studio 输出显示 fetchall 失败并且将返回帐户/登录:

Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:6460/api/v1/Lehrer/GetAll application/json 
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: Successfully validated the token.
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: HttpContext.User merged via AutomaticAuthentication from authenticationScheme: Bearer.
Microsoft.AspNetCore.Authorization.DefaultAuthorizationService:Information: Authorization failed for user: (null).
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
Microsoft.AspNetCore.Mvc.ChallengeResult:Information: Executing ChallengeResult with authentication schemes ().
Microsoft.AspNetCore.Authentication.JwtBearer.JwtBearerMiddleware:Information: AuthenticationScheme: Bearer was forbidden.
Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware:Information: AuthenticationScheme: Identity.Application was challenged.
Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker:Information: Executed action Sam.Learning2.Controllers.LehrerController.GetAll (Sam.Learning2) in 49.7114ms
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request finished in 121.6106ms 302 
Microsoft.AspNetCore.Hosting.Internal.WebHost:Information: Request starting HTTP/1.1 GET http://localhost:6460/Account/Login?ReturnUrl=%2Fapi%2Fv1%2FLehrer%2FGetAll  

我希望我的 API 返回 401/403,而不是重定向到登录 - 当上述代码不起作用时,如何实现此目的?


更新 ASP.NET Core 2.x

ASP.NET Core 2.0 中的授权发生了一些变化。下面的答案仅适用于 ASP.NET Core 1.x。对于 ASP.NET Core 2.0 请参阅此answer https://stackoverflow.com/a/43962236/455493和这个GitHub公告 https://github.com/aspnet/Announcements/issues/232.

ASP.NET 核心 1.x

你似乎忘记的是app.UseIdentity() also 注册cookie中间件 https://github.com/aspnet/Identity/blob/rel/1.1.0/src/Microsoft.AspNetCore.Identity/BuilderExtensions.cs#L35-L40.

var options = app.ApplicationServices.GetRequiredService<IOptions<IdentityOptions>>().Value;
app.UseCookieAuthentication(options.Cookies.ExternalCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorRememberMeCookie);
app.UseCookieAuthentication(options.Cookies.TwoFactorUserIdCookie);
app.UseCookieAuthentication(options.Cookies.ApplicationCookie);

ASP.NET Core Identity 设置AutomaticChallange to true对于饼干(ApplicationCookie) 中间件 (查看来源 https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware#creating-a-middleware-pipeline-with-iapplicationbuilder)。因此重定向到/Account/Login?ReturnUrl。您需要在“身份”中禁用此选项。

services.AddIdentity(options =>
{
    options.Cookies.ApplicationCookie.AutomaticChallenge = false;
});

If you really想要拥有 Identity 的 Auth(登录网页)和 JWT,您需要根据 url 注册中间件。所以即app.UseIdentity()仅注册非 api url,而 Jwt 中间件仅注册以以下开头的 url/api.

你可以这样做.MapWhen (docs https://learn.microsoft.com/en-us/aspnet/core/fundamentals/middleware#creating-a-middleware-pipeline-with-iapplicationbuilder).

app.MapWhen(context => !context.Request.Path.StartsWith("/api"), branch => 
{
    branch.UseIdentity();
});

Now branch.UseIdentity()仅用于不以以下形式开头的 URL/api,通常是重定向到的 MVC 视图/Account/Login是所期望的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

ASP.Net Core - API 身份验证错误时没有重定向 的相关文章

随机推荐