2013-11-21 121 views
4

我試圖在DelegatingHandler中實現身份驗證。下面是一個例子。無法從授權處理程序Web API返回未授權的HTTP

public class AuthHandler: DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     var auth = request.Headers.Authorization; 
     if (!auth.Scheme.Equals("UberSecureScheme")) 
     { 
      return new Task<HttpResponseMessage>(() => new HttpResponseMessage(HttpStatusCode.Unauthorized) 
       { 
        Content = new StringContent("You have no token") 
       }); 
     } 

     return base.SendAsync(request, cancellationToken); 
    } 
} 

這永遠不會執行任務,永遠不會返回任何響應。如果我改變代碼來做一些任務延續的事情,就像我看過一些例子那麼Controller首先被執行。

return base.SendAsync(request, cancellationToken) 
      .ContinueWith(task => 
      { 
       var response = task.Result; 
       response.StatusCode = HttpStatusCode.Unauthorized; 
       return response; 
      }); 

這顯然是一場災難。我不能讓別人刪除,然後告訴他們他們未經授權就這麼做。

我也遇到過有人說只是拋出一個HTTPResponseException。無論我在那裏放置什麼狀態碼(404,401,無論什麼),瀏覽器總是會有500個內部服務器錯誤。

回答

7
if (!auth.Scheme.Equals("UberSecureScheme")) 
{ 
    var response = request.CreateResponse(HttpStatusCode.Unauthorized); 
    response.ReasonPhrase = "You have no token"; 
    return Task.FromResult<HttpResponseMessage>(response); 
} 
+0

你在開玩笑吧。整理出來。你能告訴我爲什麼/這是如何工作的,但沒有別的事情? – uriDium

+0

當'new HttpResponseMessage'沒有時'request.CreateResponse'保存有關請求的信息。至於'ContinueWith',它調用base方法,所以控制器被執行。 – Vladimir

+1

我明白爲什麼'ContinueWith'是錯誤的。我不敢相信人們會這樣做auth的例子,因爲從代碼和一個簡單的測試中可以清楚的看出它仍然在執行控制器。但我不是100%確定'new HttpResponseMessage'。如果我手動複製了來自請求的更多信息,它會起作用嗎? – uriDium

0

您可以使用異步/等待。 我輸入它,而不是複製/粘貼 - 不要問,所以希望沒有輸入錯誤.... :)

protected async override Task<HttpResponseMessage>    SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
var response = await base.SendAsync(request, cancellationToken); 
if (HttpContext.Current.User == null) { 
    HttpResponseMessage errorResponse = new HttpResponseMessage(); 
    errorResponse.Headers.Add("WWW-Authenticate", "Some auth related message"); 
    errorResponse.StatusCode = HttpStatusCode.Unauthorized; 
    return errorResponse; 
} 
return response;