Asp.net

ASP.NET Core - 從 AuthenticationHandler 獲取消息

  • June 21, 2021

我已經實現了AuthenticationHandler. 它返回AuthenticationResult.Fail("This is why you can't log in");

我本來希望這條消息最終出現在正文中,或者至少出現在 HTTP 狀態文本中,但我得到的是一個空白的 401 響應。

有沒有辦法為 ASP.NET 核心中的失敗身份驗證嘗試提供附加資訊?

覆蓋 HandleChallengeAsync:

在下面的範例中,這failReason是我的 AuthenticationHandler 實現中的一個私有欄位。我不知道這是否是傳遞失敗原因的最佳方式。但是在我的測試中AuthenticationPropertiesAuthenticateResult.Fail方法並沒有通過。HandleChallengeAsync

public class CustomAuthenticationHandler<TOptions> : AuthenticationHandler<TOptions> where TOptions : AuthenticationSchemeOptions, new()
{
   private string failReason;

   public CustomAuthenticationHandler(IOptionsMonitor<TOptions> options
       , ILoggerFactory logger
       , UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { }

   protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
   {
       failReason = "Reason for auth fail";
       return AuthenticateResult.Fail(failReason);
   }

   protected override Task HandleChallengeAsync(AuthenticationProperties properties)
   {
       Response.StatusCode = 401;

       if (failReason != null)
       {
           Response.HttpContext.Features.Get<IHttpResponseFeature>().ReasonPhrase = failReason;
       }

       return Task.CompletedTask;
   }
}

來自文件:https ://docs.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.authentication.authenticationhandler-1?view=aspnetcore-2.2

如果有問題的身份驗證方案將身份驗證互動作為其請求流的一部分處理,則覆蓋此方法以處理 401 質詢問題。(例如添加響應標頭,或將登錄頁面或外部登錄位置的 401 結果更改為 302。)

來源: https ://github.com/aspnet/Security/blob/master/src/Microsoft.AspNetCore.Authentication/AuthenticationHandler.cs#L201

我在我的自定義中間件中使用了這段程式碼來返回questionDetails響應。

public async Task Invoke(HttpContext httpContext)
{
   await this.Next(httpContext);

   if (httpContext.Response.StatusCode == StatusCodes.Status401Unauthorized)
   {
       var authenticateResult = await httpContext.AuthenticateAsync();

       if (authenticateResult.Failure != null)
       {
           var routeData = httpContext.GetRouteData() ?? new RouteData();
           var actionContext = new ActionContext(httpContext, routeData, new ActionDescriptor());

           var problemDetails = this.ProblemDetailsFactory.CreateProblemDetails(httpContext,
               statusCode: httpContext.Response.StatusCode,
               detail: authenticateResult.Failure.Message);

           var result = new ObjectResult(problemDetails)
           {
               ContentTypes = new MediaTypeCollection(),
               StatusCode = problemDetails.Status,
               DeclaredType = problemDetails.GetType()
           };

           await this.Executor.ExecuteAsync(actionContext, result);
       }
   }
}

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