2017-05-25 62 views
0

我有几个索赔添加到了我的JWT令牌。在任何方法中,我的API中的每一个控制器都会得到身份并检查这些声明。我想减少代码的重复,并从一个共同的地方获得我的主张;可能在startup.cs中分配它们。如何为所有WebApi控制器获得一次JWT索赔

例如,我有一个DemoController来实现基本的CRUD操作。同样的代码往往出现在我所有的方法,在我所有的控制器:

var identity = (ClaimsPrincipal)Thread.CurrentPrincipal; 

var region = identity.Claims.Where(c => c.Type == ClaimType.Region).Select(c => c.Value).SingleOrDefault(); 

var role = identity.Claims.Where(c => c.Type == ClaimType.Role).Select(c => c.Value).SingleOrDefault(); 

var responseType = identity.Claims.Where(c => c.Type == ClaimType.ResponseType).Select(c => c.Value).SingleOrDefault(); 

If (region == "some region") 
{ 
} 

有没有什么方法可以让我避免重复的代码都在我的API?我想用可以在整个的WebAPI控制器间共享的对象,这样我可以写我这样的代码来代替:

if(ApiUser.Region == "Some Region") 
{ 
    // DO SOMETHING 
} 

我已经使用Ninject依赖注入。我认为有可能在Startup.cs中创建我的ApiUser对象,然后将ApiUser注入到每个控制器中,但我不完全确定如何做到这一点,如果可能的话或者是否存在更好的替代方案。

所有建议都欢迎!

+0

或者创建一个封装所有重复代码并让控制器继承它的基础控制器。 – Nkosi

+0

我认为你的想法是创建一个封装了这些信息的类,并将该类注入到控制器中,这是可行且合理的解决方案。将它包装在一个界面中,以便测试它。我总是喜欢注入而不是继承。 –

+0

与构造函数注入路线一起的问题是,用户/主体在注入控制器时尚未设置。 – Nkosi

回答

0

您可以创建一个ClaimsAuthenticationManager的实现来执行查询声明或者甚至向JWT添加其他自定义声明。

public class MyClaimsAuthenticationManager : ClaimsAuthenticationManager 
{ 
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal) 
    { 
     if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated) 
     // build up your ApiUser class here 

    } 
    return incomingPrincipal; 
} 

然后,您可以使用您的ApiUser类在每个控制器中进行检查;甚至更好,使用自定义AuthorizationAttribute为您想要做的每种类型的检查。