6

Owin中間件實現是否可以在執行Web API控制器之前添加聲明?用Owin Middleware添加聲明

創建一個OwinMiddleware實施並增加了身份:

var id = new ClaimsIdentity(); 
id.AddClaim(new Claim("Whatever", "is possible")); 
context.Authentication.User.AddIdentity(id); 

await Next.Invoke(context); 

然而,即使這個調用方法調用不被更新的身份(只是內部權利要求數組)。而且,控制器在執行時當然不會得到新的虛擬聲明。

想法?

+1

在JabbR的Owin大堂@Pinpoint聊天后,似乎到認證線的唯一途徑就是通過IAppBuilder的UseOAuthBearerAuthentication指定自定義提供商。然後可以將聲明添加到身份上下文中(context.Ticket.Identity.AddClaim(...))。這是根據請求完成的。 – 2015-02-18 13:40:31

回答

1

您可能會發現有用的Authorizate屬性繼承和擴展以滿足您的要求:

public class DemoAuthorizeAttribute : AuthorizeAttribute 
    {  

     public override void OnAuthorization(System.Web.Http.Controllers.HttpActionContext actionContext){ 
      if (Authorize(actionContext)){ 
       return; 
      } 
      HandleUnauthorizedRequest(actionContext); 
     } 

     protected override void HandleUnauthorizedRequest(System.Web.Http.Controllers.HttpActionContext actionContext){ 
      var challengeMessage = new System.Net.Http.HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized; 

//Adding your code here 
var id = new ClaimsIdentity(); 
id.AddClaim(new Claim("Whatever", "is possible")); 
context.Authentication.User.AddIdentity(id); 

      challengeMessage.Headers.Add("WWW-Authenticate", "Basic"); 
      throw new HttpResponseException(challengeMessage); 
     } 

     private bool Authorize(System.Web.Http.Controllers.HttpActionContext actionContext){ 
      try{ 
       var someCode = (from h in actionContext.Request.Headers where h.Key == "demo" select h.Value.First()).FirstOrDefault(); 

       // or check for the claims identity property. 
       return someCode == "myCode"; 
      } 
      catch (Exception){ 
       return false; 
      } 
     } 
    } 

而在你的控制器:

[DemoAuthorize] 
public class ValuesController : ApiController{ 

這裏是的WebAPI授權的其他自定義實行鏈接:

http://www.piotrwalat.net/basic-http-authentication-in-asp-net-web-api-using-membership-provider/

+0

我發現的唯一問題就是如果您支持多種授權方法,例如OAuth和HMAC你必須在多個地方實現索賠豐富,因此我的答案在下面。 – 2016-11-16 15:56:19

0

目前已經是一個類,它可以提供豐富索賠ClaimsAuthenticationManager,您可以延長因此處理您的特定領域的要求,例如...

public class MyClaimsAuthenticationManager : ClaimsAuthenticationManager 
{ 
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal) 
    { 
     if (!incomingPrincipal.Identity.IsAuthenticated) 
     { 
      return base.Authenticate(resourceName, incomingPrincipal); 
     } 

     return AddApplicationClaims(incomingPrincipal); 
    } 

    private ClaimsPrincipal AddApplicationClaims(ClaimsPrincipal principal) 
    { 
     // TODO: Add custom claims here based on current principal. 

     return principal; 
    } 
} 

下一個任務是提供合適的中間件調用此方法。對於我的項目,我寫了下面的類...

/// <summary> 
/// Middleware component to apply claims transformation to current context 
/// </summary> 
public class ClaimsTransformationMiddleware 
{ 
    private readonly Func<IDictionary<string, object>, Task> next; 
    private readonly IServiceProvider serviceProvider; 

    public ClaimsTransformationMiddleware(Func<IDictionary<string, object>, Task> next, IServiceProvider serviceProvider) 
    { 
     this.next = next; 
     this.serviceProvider = serviceProvider; 
    } 

    public async Task Invoke(IDictionary<string, object> env) 
    { 
     // Use Katana's OWIN abstractions 
     var context = new OwinContext(env); 

     if (context.Authentication != null && context.Authentication.User != null) 
     { 
      var manager = serviceProvider.GetService<ClaimsAuthenticationManager>(); 
      context.Authentication.User = manager.Authenticate(context.Request.Uri.AbsoluteUri, context.Authentication.User); 
     } 

     await next(env); 
    } 
} 

然後接線延伸......

public static class AppBuilderExtensions 
{ 
    /// <summary> 
    /// Add claims transformation using <see cref="ClaimsTransformationMiddleware" /> any depdendency resolution is done via IoC 
    /// </summary> 
    /// <param name="app"></param> 
    /// <param name="serviceProvider"></param> 
    /// <returns></returns> 
    public static IAppBuilder UseClaimsTransformation(this IAppBuilder app, IServiceProvider serviceProvider) 
    { 
     app.Use<ClaimsTransformationMiddleware>(serviceProvider); 

     return app; 
    } 
} 

我知道這是服務定位器的反模式,但使用的IServiceProvider是集裝箱中性並且似乎是將依賴關係納入Owin中間件的可接受方式。

最後,你需要在你的啓動來這樣使用,下面的例子假定團結和註冊/暴露出IServiceLocator屬性...

// Owin config 
app.UseClaimsTransformation(UnityConfig.ServiceLocator); 
0

這是我結束了在加入中間件owin一個新的要求,基於OP關於鉤入UseOAuthBearerAuthentication的評論。它使用IdentityServer3.AccessTokenValidation,它在內部調用UseOAuthBearerAuthentication並將OAuthBearerAuthenticationProvider傳遞給它。

using System.Security.Claims; 
using System.Threading.Tasks; 
using IdentityServer3.AccessTokenValidation; 
using Owin; 
using Microsoft.Owin.Security.OAuth; 

//... 

public void Configuration(IAppBuilder app) 
{ 
    app.UseIdentityServerBearerTokenAuthentication(new IdentityServerBearerTokenAuthenticationOptions 
    { 
     Authority = "http://127.0.0.1/identityserver", 
     TokenProvider = new OAuthBearerAuthenticationProvider 
     { 
      OnValidateIdentity = AddClaim 
     } 
    }); 
} 

private Task AddClaim(OAuthValidateIdentityContext context) 
{ 
    context.Ticket.Identity.AddClaim(new Claim("test", "123")); 
    return Task.CompletedTask; 
}