如何告诉属性使用自定义消息处理程序的基本身份validation?

我正在遵循Badri L.的Pro ASP .NET Web API安全性第8章,试图为将由HTTP / JS客户端使用的Web应用程序实现基本身份validation。

我已将以下身份validation处理程序添加到我的WebAPI项目中:

public class AuthenticationHandler : DelegatingHandler { private const string SCHEME = "Basic"; protected async override Task SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { try { // Request Processing var headers = request.Headers; if (headers.Authorization != null && SCHEME.Equals(headers.Authorization.Scheme)) { Encoding encoding = Encoding.GetEncoding("iso-8859-1"); // etc 

当我使用[Authorize]在我的API中修饰方法并在上面的if语句中设置断点时, headers.Authorization在第一次请求时为null。 如果我继续这个中断,if语句再次被命中,这次使用headers.Authorization.Scheme作为“Negotiate”,而不是“Basic”:

在此处输入图像描述

我在WebApiConfig中注册了我的处理程序:

 config.MessageHandlers.Add(new AuthenticationHandler()); 

但是我不知道为什么Authorize属性不尊重基本身份validation,或者为什么 – 因为该方案不是“基本”而我的处理程序中的if()返回false – 我从我的API控制器获取数据当我应该获得401 Unauthorized

我没有在web.config中指定任何authenticationType。

知道我做错了什么吗?

编辑:完整处理程序:

 public class AuthenticationHandler : DelegatingHandler { private const string SCHEME = "Basic"; protected async override Task SendAsync(HttpRequestMessage request, System.Threading.CancellationToken cancellationToken) { try { // Request Processing var headers = request.Headers; if (headers.Authorization != null && SCHEME.Equals(headers.Authorization.Scheme)) { Encoding encoding = Encoding.GetEncoding("iso-8859-1"); string credentials = encoding.GetString(Convert.FromBase64String(headers.Authorization.Parameter)); string[] parts = credentials.Split(':'); string userId = parts[0].Trim(); string password = parts[1].Trim(); // TODO: Authentication of userId and Pasword against credentials store here if (true) { var claims = new List { new Claim(ClaimTypes.Name, userId), new Claim(ClaimTypes.AuthenticationMethod, AuthenticationMethods.Password) }; var principal = new ClaimsPrincipal(new[] {new ClaimsIdentity(claims, SCHEME)}); Thread.CurrentPrincipal = principal; if (HttpContext.Current != null) HttpContext.Current.User = principal; } } var response = await base.SendAsync(request, cancellationToken); // Response processing if (response.StatusCode == HttpStatusCode.Unauthorized) { response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue(SCHEME)); } return response; } catch (Exception) { // Error processing var response = request.CreateResponse(HttpStatusCode.Unauthorized); response.Headers.WwwAuthenticate.Add(new AuthenticationHeaderValue(SCHEME)); return response; } } } 

当我使用[Authorize]在我的API中修饰方法并在上面的if语句中设置断点时,headers.Authorization在第一次请求时为null。

这是预料之中的。 这就是它应该如何工作。 浏览器将显示弹出窗口,仅在收到401时才从用户获取凭据。后续请求将具有基本方案中具有凭据的授权标头。

如果我继续这个中断,if语句再次被命中,这次使用headers.Authorization.Scheme作为“Negotiate”,而不是“Basic”:

是的,正如Dominick(是Dominick?)所回答的那样,您启用了Windows身份validation,这就是您从浏览器返回协商方案的原因。 您必须在配置中或使用IIS管理器禁用所有身份validation方法。

但是我不知道为什么Authorize属性不尊重基本身份validation,或者为什么 – 因为该方案不是“基本”而我的处理程序中的if()返回false – 我从我的API控制器获取数据当我应该获得401 Unauthorized。

授权属性对基本身份validation一无所知。 所有它关心的是身份是否经过身份validation。 由于您启用了匿名身份validation(我猜是这种情况),Authorize属性很高兴,并且消息处理程序响应处理部分没有401添加WWW-Authenticate响应头,表明Web API需要Basic方案中的凭据。

您似乎已在IIS中为您的应用启用了Windows身份validation。 禁用config(system.web和system.webServer)中的所有身份validation方法并允许匿名,因为您在消息处理程序中执行自己的身份validation。

我认为你需要在global.asa上注册处理程序

这篇文章看起来不错: http : //byterot.blogspot.com.br/2012/05/aspnet-web-api-series-messagehandler.html

你的global.asa.cs会有这样的东西:

 public static void Application_Start(GlobalFilterCollection filters) { //... GlobalConfiguration.Configuration.MessageHandlers.Add(new AuthenticationHandler()); }