2013-11-21 86 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;