其他分享
首页 > 其他分享> > android-Web API 2身份验证筛选器-存在Authorization标头时不触发AuthenticateAsync

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