Fork me on GitHub

.NetCore中如何实现权限控制 基于Claim角色、策略、基于Claim功能点处理

.NetCore中如果实现权限控制的问题,当我们访问到一个Action操作的时候,我们需要进行权限控制

基于claims 角色控制

基于角色控制总觉得范围有点过大,而且控制起来感觉也不是太好,举一个例子就是,一个添加操作Action,如果通过角色控制,通过写起来就有点痛苦

如果一个添加操作有20个角色都可以访问,那么在角色上需要指定好所有的角色,通过用户中的角色Claims匹配访问

通过Claims中的

  claims.Add(new Claim(ClaimTypes.Role, "rolecode"));
 [Authorize(Roles ="rolecode")]

当然也可以通过自定实现 接口,下面功能点类似的方式,通过角色服务获取判断,这里需要处理的就是获取 角色属性上的角色名称 ActionDescriptor  、 IAuthorizeData 获取 Role的值

 if (!context.HttpContext.User.IsInRole("rolename"))
                {
                    context.Result = new ForbidResult();
                }

基于策略控制

当然也可以通过策略处理,策略就是一个大杂烩,提供了不同的配置方案如下面给出的例子

 [Authorize(Policy ="policyname")]
  services.AddAuthorization(options => {
                options.AddPolicy("policyname", policy => {
                    policy.RequireRole("rolename1", "rolename2");
                    policy.RequireClaim("claimname");
                    policy.RequireUserName("username");
                } );
            });

上面的方式感觉不是太好,有的时候我们需要动态的配置功能点权限

比如,在系统中添加了一个角色,这个角色也拥有管理其中的一个Action权限,这里就需要去设置action上的Role规则,如果使用基于角色Claim控制就显得很不好了

如果采用策略方式的话都需要去修改代码,而且还需要对系统很熟悉,那些地方使用了那些策略或者角色,这样也不行,所以我们采用下面的Claims功能点控制

基于claims 功能点控制

这里我们需要去创建一个属性(Attribute)标签,且实现 IAsyncAuthorizationFilter 接口

如果功能点不多,数据量比较小的情况下,可以把功能点信息直接添加到 claims中,如果过多 只能动态获取,或者动态读取缓存提高效率

下面看下实现代码

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
    public class AuthorizeCodeAttribute : Attribute, IAsyncAuthorizationFilter
    {
        public AuthorizeCodeAttribute(string name)
        {
            Name = name;
        }

        public string Name { get; set; }
        public async Task OnAuthorizationAsync(AuthorizationFilterContext context)
        {

          
                if (!context.HttpContext.User.HasClaim(c => c.Value == Name))
                {
                    context.Result = new ForbidResult();
                }
            await Task.CompletedTask;


        }
    }

接下来就是在Action上指定好相关的功能点编码就行了

 [AuthorizeCode(PermissionsConfig.ClassAdd)]
 public IActionResult Create()
{
            return View();
}

如果Claims信息过多可以通过获取服务动态查询得到后进行验证 或者 缓存服务(Redis、Cache)得到,在Startup中DI上你的服务即可

var services= context.HttpContext.RequestServices.GetService<T>();

对于Claims信息的处理可以在登录 SignIn 的时候写入相关的Claims身份信息即可,这里需要提到的是 ClaimsIdentity(身份信息)、ClaimsPrincipal(身份人,当事人,身份所有人)

 

posted @ 2018-09-13 16:36  龙码精神  阅读(6743)  评论(2编辑  收藏  举报