2015-02-05 34 views
10

我实现了基于on these blog posts在Asp.Net网络API使用OAuth的都和基本身份验证与Owin

它运作良好,包括刷新令牌逻辑我的Web API项目OAuth认证。

我想为基本身份验证添加一个选项,以及一些调度任务的调用。

我试着添加一个基本的身份验证解决方案作为中间件,但我仍然得到401要求持票人令牌。

我可以通过从这些api调用中删除[Authorize]属性并在代码中手动检查用户是否已通过验证,但似乎是解决此问题的错误方法。

有没有一种方法可以同时支持使用OWin进行基本身份验证和OAuth身份验证?

回答

7

如何与要实现与属性[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() 
{ 
} 

注意我们是如何创建声明身份认证方式设置为Basic,您可以PU t你想要的任何声明。

+0

我在过去的项目中使用过滤器进行自定义验证,我猜想在API中的几个调用主要使用其他验证方案,这比在每次调用时都要执行的Owin中间件更有意义。 – EShy 2015-02-10 18:09:39