.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(身份人,當事人,身份所有人)