android-Web API 2身份验证筛选器-存在Authorization标头时不触发AuthenticateAsync
作者:互联网
当网站在我的本地IIS上运行时,我无法启动简单的身份验证筛选器,这是一个奇怪的问题.如果我发布到Azure,则身份验证筛选器可以正常工作.因此,我怀疑本地IIS上有一个设置,但除了在网站的“身份验证”设置下启用“基本身份验证”之外,我真的不知道它还有什么其他设置.
我创建了一个空Web API 2网站,该网站创建了值控制器.然后,我为身份验证过滤器添加了以下样板代码:-
public class BasicAuthenticationAttribute : Attribute, IAuthenticationFilter
{
public bool AllowMultiple { get { return false; } }
public Task AuthenticateAsync(HttpAuthenticationContext context,
CancellationToken cancellationToken)
{
var req = context.Request;
// Get credential from the Authorization header
//(if present) and authenticate
if (req.Headers.Authorization != null &&
"Basic".Equals(req.Headers.Authorization.Scheme,
StringComparison.OrdinalIgnoreCase))
{
if (TryValidateCredentials(req.Headers.Authorization.Parameter))
{
var claims = new List<Claim>()
{
new Claim(ClaimTypes.Name, "AuthenticatedUser"),
new Claim(ClaimTypes.Role, "user")
};
var id = new ClaimsIdentity(claims, "Token");
var principal = new ClaimsPrincipal(new[] { id });
// The request message contains valid credential
context.Principal = principal;
}
else
{
// The request message contains invalid credential
context.ErrorResult = new UnauthorizedResult(
new AuthenticationHeaderValue[0], context.Request);
}
}
return Task.FromResult(0);
}
private bool TryValidateCredentials(string creds)
{
string pair;
try
{
pair = Encoding.UTF8.GetString(Convert.FromBase64String(creds));
}
catch (FormatException)
{
return false;
}
catch (ArgumentException)
{
return false;
}
var ix = pair.IndexOf(':');
if (ix == -1) return false;
var username = pair.Substring(0, ix);
var pw = pair.Substring(ix + 1);
if (username != "" && pw != "")
{
return true;
}
else
{
return false;
}
}
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", "Please supply valid credentials"));
}
return response;
}
}
}
然后,我为ValuesController类添加了以下属性:
[TestBA.Filters.BasicAuthentication]
[Authorize]
我的默认IIS7网站(Windows 7 Home Premium)指向项目文件夹,如果我运行和调试w3wp.exe(托管v4),则在http://192.168.1.11/api/values处访问网站会导致在AuthenticateAsync开始时出现断点.如果我从Android代码调用,我也会遇到相同的断点.但是,如果我使用AsyncHttpClient.setBasicAuth设置基本身份验证标头,或者手动添加标头,则断点将永远不会被命中,并且我会立即获得未经授权的HTTP响应.如果我将网站发布到Azure,则可以正常工作,因此未经调用而未调用AuthenticateAsync的响应仅发生在本地IIS上.如果有帮助,请参见以下Android代码:-
private void setBasicAuth(AsyncHttpClient client){
client.setBasicAuth("test", "test");
/*client.addHeader("Authorization",
"Basic " + android.util.Base64.encodeToString(
"test:test".getBytes(),
android.util.Base64.NO_WRAP
)
);*/
}
我什至在Visual Studio Community 2013中打开了所有可能的异常,以查看是否缺少运行时异常或本机代码异常,但是什么也没有.如果有任何相关性,我正在Android上使用loopj库.如果有任何相关性,我也在本地Android IDE“ AIDE”上编写Android代码. IIS日志显示请求是否传入并通过401响应,无论我是否使用基本身份验证标头进行呼叫,因此,在两种情况下,请求无疑都有效.
如果有人能阐明为什么在IIS的本地副本上的请求中指定了基本身份验证标头时,为什么Web API 2身份验证筛选器不会触发,那么我将不胜感激.
解决方法:
我在工作PC上重写了该测试应用程序,但无法使其失败,因此这是一个发现差异的案例.
答案实际上很明显.我盲目地在本地IIS上启用了“基本身份验证”,因为我自然希望在Web API 2网站中使用基本身份验证.错误!在IIS中启用基本身份验证会告诉IIS拦截并处理所有基本身份验证标头,而不将其传递给网站.实际上,它尝试将用户名和密码与本地PC用户帐户进行匹配.我需要的是在IIS中禁用基本身份验证,然后将授权HTTP标头传递到我的网站,并启动AuthenticateAsync.
标签:asp-net-web-api2,iis-7,basic-authentication,android 来源: https://codeday.me/bug/20191028/1953229.html