Asp.net-Core

為什麼我需要設置 DefaultForbidScheme

  • March 21, 2022

在 WebAPI .net 核心項目中,我創建了一個驗證 api 密鑰的中間件類。通過驗證它,它在呼叫方法中檢索密鑰具有的權限(使用者或管理員)。

我通過一個開關來設置原理

GenericIdentity identity = new GenericIdentity("API");
GenericPrincipal principle = null;

//we have a valid api key, so set the role permissions of the key
switch (keyValidatorRes.Role)
{
  case Roles.User:
       principle = new GenericPrincipal(identity, new[] { "User" });  
       context.User = principle;
       break;
   case Roles.Admin:
       principle = new GenericPrincipal(identity, new[] { "Admin" });         
       context.User = principle;
       break;
   default:
       principle = new GenericPrincipal(identity, new[] { "Other" });
       context.User = principle;
       break;
}

在控制器方法上我有

[Authorize(Roles = "Admin")]

驗證經過身份驗證的 api 密鑰的角色

如果使用者有管理原則,它會按預期進行。但是,如果它有使用者或其他原則,那麼我會收到關於

沒有 DefaultForbidScheme

我四處搜尋並使用客戶方案將身份驗證添加到我的 startup.cs

services.AddAuthentication(options=> {
      options.DefaultForbidScheme = "forbidScheme";
      options.AddScheme<AuthSchemeHandle>("forbidScheme", "Handle Forbidden");
});

並創建了AuthSchemeHandle

public class AuthSchemeHandle : IAuthenticationHandler
{
   private HttpContext _context;

   public Task<AuthenticateResult> AuthenticateAsync()
   {
       return Task.FromResult(AuthenticateResult.NoResult());
   }

   public Task ChallengeAsync(AuthenticationProperties properties)
   {
       throw new NotImplementedException();
   }

   public Task ForbidAsync(AuthenticationProperties properties)
   {
       return Task.FromResult(AuthenticateResult.Fail("Failed Auth"));
   }

   public Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
   {
       _context = context;
       return Task.CompletedTask;
   }
}

現在,如果該原則沒有 Admin,它會失敗而不會出現錯誤,但 API 上返回的響應200沒有內容。我期待4xx回复消息“驗證失敗”

我只是想弄清楚為什麼它不像預期的那樣,雖然它看起來“固定”我不明白它是如何修復它的。

我應該這樣做有更好的方法嗎?

為什麼它不像預期的那樣,雖然它似乎“固定”我不明白它是如何修復它的。

IAuthenticationHandler.ForbidAsync()身份驗證處理程序呼叫方法時沒有黑魔法。我們必須自己做相關的事情。簡而言之,StatusCode=403根據需要設置。

public async Task ForbidAsync(AuthenticationProperties properties)
{
   properties = properties ?? new AuthenticationProperties();
   _context.Response.StatusCode = 403;
   // ...
   return Task.CompletedTask;    
}

附帶說明一下,您不需要 return aTask.FromResult()因為它不關心結果。

我應該這樣做有更好的方法嗎?

ASP.NET Core 團隊為我們提供了一個抽像類AuthenticationHandler來處理身份驗證。這個抽像類有一個內置的實現ForbidAsync(AuthenticationProperties properties)(以及其他公共方法)。所以很容易擴展這個抽像類,如下所示:

public class MyAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions>
{
   public MyAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) 
       : base(options, logger, encoder, clock)
   {
   }

   protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
   {
       return AuthenticateResult.NoResult();
   }
}

最後,添加認證服務的配置:

services
   .AddAuthentication(options=>{
       options.DefaultAuthenticateScheme = "forbidScheme";
       options.DefaultForbidScheme = "forbidScheme";
       options.AddScheme<MyAuthenticationHandler>("forbidScheme", "Handle Forbidden");
   });

它應該按預期工作。

引用自:https://stackoverflow.com/questions/54578426