我通过发送会话令牌使用自定义身份验证机制。在DelegatingHandler中检查令牌的存在,DelegatingHandler根据情况设置当前主体。如果主体未被授权调用ApiController方法,则控制器发送401 Unauthorized状态。由于RFC 2616需要在发送401响应时始终设置WWW-Authenticate标头,因此我的DelegatingHandler负责处理此问题。
现在,在Web API自托管的情况下,应响应401的请求可以在Windows 7上正常运行,但在Windows Server 2003上它会因“远程主机强行关闭现有连接”而死亡。此外,我注意到控制器方法中的断点在W2k3上被击中两次,而在Win7中被击中一次,好像HttpClient在收到401响应时以某种方式重试了请求。
当我使用WWW-Authenticate标头取消注释该行时,该程序正常工作。请参阅下面的代码示例,以获取控制台应用程序中的简约再现示例。
TestController.cs:
public class TestController : ApiController
{
public HttpResponseMessage Get()
{
return Request.CreateErrorResponse(HttpStatusCode.Unauthorized, "go away");
}
}
AuthenticationHandler.cs:
public class AuthenticationHandler : DelegatingHandler
{
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
return base.SendAsync(request, cancellationToken).ContinueWith<HttpResponseMessage>(task =>
{
HttpResponseMessage response = task.Result;
if ( response.StatusCode == HttpStatusCode.Unauthorized &&
!response.Headers.Contains("WWW-Authenticate") )
{
// comment out this line and the code works
response.Headers.Add("WWW-Authenticate", "SessionToken");
}
return response;
});
}
}
的Program.cs:
static void Main(string[] args)
{
HttpSelfHostConfiguration config = new HttpSelfHostConfiguration("http://localhost:81");
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}"
);
config.MessageHandlers.Add(new AuthenticationHandler());
using ( HttpSelfHostServer server = new HttpSelfHostServer(config) )
using ( HttpClient client = new HttpClient() )
{
server.OpenAsync().Wait();
try
{
HttpResponseMessage response = client.GetAsync("http://localhost:81/api/test").Result;
Console.Out.WriteLine(response.StatusCode);
}
catch ( AggregateException ex )
{
Console.Out.WriteLine(ex.ToString());
}
server.CloseAsync().Wait();
}
Console.In.ReadLine();
}
我是否正确调用了API?什么想法可能是错的?