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