Asp.net-Web-Api

在身份驗證過濾器中的 ChallengeAsync 方法的上下文中設置結果

  • July 12, 2014

這個問題與我在這裡提供的答案有關。OP的評論讓我思考了一下。我建議在身份驗證過濾器IHttpActionResult的方法中使用這樣的類實現。ChallengeAsync

public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
                                 CancellationToken cancellationToken)
{
   context.Result = new ResultWithChallenge(context.Result);
   return Task.FromResult(0);
}

public class ResultWithChallenge : IHttpActionResult
{
   private readonly IHttpActionResult next;

   public ResultWithChallenge(IHttpActionResult next)
   {
       this.next = next;
   }

   public async Task<HttpResponseMessage> ExecuteAsync(
                               CancellationToken cancellationToken)
   {
       var response = await next.ExecuteAsync(cancellationToken);
       if (response.StatusCode == HttpStatusCode.Unauthorized)
       {
           response.Headers.WwwAuthenticate.Add(
                  new AuthenticationHeaderValue("Basic", "realm=localhost"));
       }

       return response;
   }
}

取而代之的是,我可以ChallengeAsync像這樣簡化。

public Task ChallengeAsync(HttpAuthenticationChallengeContext context,
                            CancellationToken cancellationToken)
{
   var result = await context.Result.ExecuteAsync(cancellationToken);
   if (result.StatusCode == HttpStatusCode.Unauthorized)
   {
       result.Headers.WwwAuthenticate.Add(
                    new AuthenticationHeaderValue("Basic", "realm=localhost"));
   }
   context.Result = new ResponseMessageResult(result);
}

這使我免於創建一個實現類IHttpActionResult,但這是正確的方法嗎?我有一種不安的感覺,從性能的角度來看這有點糟糕,因為感覺就像我正在將操作結果轉換為 HttpResponseMessage 並返回到操作結果。與使用上面的程式碼相比,任何關於此處需要一個單獨的類的指針IHttpActionResult都將像我建議的那樣實現。

目的是使用第一種方法而不是第二種方法。例如,請參閱基本身份驗證範例(也可用於 MVC),它遵循第一種方法: http ://aspnet.codeplex.com/SourceControl/latest#Samples/WebApi/BasicAuthentication/ReadMe.txt

第二種方法大多有效。我不會太在意性能的觀點;無論哪種方式,您都在分配一個操作結果對象和一個響應消息對象,所以我看不出有太大的區別。

但是,我推薦第一種方法有幾個原因:

  1. 第二種方法在 MVC 中的工作方式不同。MVC 和 Web API 都有身份驗證過濾器,它們的工作方式基本相同。但是在 MVC 中,沒有等效於 ResponseMessageResult(HttpContext 會根據需要進行更新,而不是返回一個 HttpResponseMessage 可以被每個呼叫者在堆棧中替換)。如果您的身份驗證過濾器有一個 MVC 實現,那麼您最終可能會在那裡執行第一種方法。
  2. 它稍微改變了預期的管道行為。ChallengeAsync 中的程式碼比它返回的 context.Result 中的程式碼執行得更早。例如,如果程式碼更改了 HttpRequestMessage 上的屬性並且影響了稍後過濾器的 ChallengeAsync 邏輯,則行為可能與預期不同。

該框架絕對可以更容易地實現介面;隨意對此工作項目進行投票: https ://aspnetwebstack.codeplex.com/workitem/1456

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