【问题标题】:Using both OAuth and Basic Auth in Asp.Net Web Api with Owin在带有 Owin 的 Asp.Net Web Api 中同时使用 OAuth 和基本身份验证
【发布时间】:2015-04-05 20:11:38
【问题描述】:

我已经在基于 on these blog posts 的 Web Api 项目中实现了 OAuth 身份验证

效果很好,包括刷新令牌逻辑。

我想为基本身份验证添加一个选项,以及为预定作业的几次调用添加一个选项。

我已尝试将基本身份验证解决方案添加为中间件,但我仍然收到 401 请求不记名令牌。

我可以通过从这些 api 调用中删除 [Authorize] 属性并在用户通过身份验证时手动检查代码来使其工作,但这似乎是错误的解决方法。

有没有办法使用 OWin 同时支持基本身份验证和 OAuth 身份验证?

【问题讨论】:

    标签: asp.net-web-api oauth owin


    【解决方案1】:

    您如何将您的操作或控制器属性与您想要使用属性[OverrideAuthentication] 实现基本身份验证然后创建自定义身份验证过滤器属性,该属性继承自Attribute, IAuthenticationFilter,如下代码所示

    public class BasicAuthenticationAttribute : Attribute, IAuthenticationFilter
    {
        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))
            {
                var rawCreds = req.Headers.Authorization.Parameter;
    
                var credArray = GetCredentials(rawCreds);
    
                var clientId = credArray[0];
                var secret = credArray[1];
    
                if (ValidCredentials(clientId, secret))
                {
                    var claims = new List<Claim>()
                          {
                            new Claim(ClaimTypes.Name, clientId)
                          };
    
                    var identity = new ClaimsIdentity(claims, "Basic");
                    var principal = new ClaimsPrincipal(new[] { identity });
                    // The request message contains valid credential
                    context.Principal = principal;
                }
                else
                {
                    context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request);
                }
    
            }
            else
            {
                context.ErrorResult = new UnauthorizedResult(new AuthenticationHeaderValue[0], context.Request);
            }
    
            return Task.FromResult(0);
        }
    
        private string[] GetCredentials(string rawCred)
        {
    
            var encoding = Encoding.GetEncoding("UTF-8");
    
            var cred = encoding.GetString(Convert.FromBase64String(rawCred));
    
            var credArray = cred.Split(':');
    
            if (credArray.Length == 2)
            {
                return credArray;
            }
            else
            {
                return credArray = ":".Split(':');
            }
    
        }
    
        private bool ValidCredentials(string clientId, string secret)
        {
    
            //compare the values from web.config
    
            if (clientId == secret)
            {
                return true;
            }
            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"));
                }
                return response;
            }
        }
    
        public bool AllowMultiple
        {
            get { return false; }
        }
    }
    

    现在您可以使用它来为您的控制器或操作赋予属性,如下代码所示:

     [OverrideAuthentication]
        [BasicAuthentication]
        [Route("")]
        public async Task<IHttpActionResult> Get()
    {
    }
    

    请注意我们如何创建声明身份并将身份验证方案设置为基本,您可以在此处放置任何您想要的声明。

    【讨论】:

    • 我在以前的项目中使用过滤器进行自定义身份验证,我猜对于主要使用其他身份验证方案的 API 中的一些调用,这比在每次调用时执行的 Owin 中间件更有意义一个基本的身份验证头
    猜你喜欢
    • 2015-10-11
    • 2016-12-31
    • 2018-09-02
    • 1970-01-01
    • 2019-10-07
    • 2017-01-16
    • 2014-09-15
    • 1970-01-01
    • 2013-11-16
    相关资源
    最近更新 更多