2015-02-05 37 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