【NET CORE微服务一条龙应用】第三章 认证授权与动态权限配置
【NET CORE微服務(wù)一條龍應(yīng)用】第三章 認(rèn)證授權(quán)與動態(tài)權(quán)限配置
介紹
系列目錄:【NET CORE微服務(wù)一條龍應(yīng)用】開始篇與目錄
在微服務(wù)的應(yīng)用中,統(tǒng)一的認(rèn)證授權(quán)是必不可少的組件,本文將介紹微服務(wù)中網(wǎng)關(guān)和子服務(wù)如何使用統(tǒng)一的權(quán)限認(rèn)證
主要介紹內(nèi)容為:
1、子服務(wù)如何實現(xiàn)和網(wǎng)關(guān)相同的鑒權(quán)方式
2、接口權(quán)限如何動態(tài)配置與修改
3、前后端分離模式下通用的后臺管理系統(tǒng)(用戶、權(quán)限、菜單、平臺)
需提前了解知識點:
1、Jwt (JSON Web Token)
2、ClaimsPrincipal
3、Microsoft.AspNetCore.Authorization、AuthorizationPolicy、AuthorizationHandler
子服務(wù)和網(wǎng)關(guān)鑒權(quán)方式
首先我們需要了解一下Ocelot網(wǎng)關(guān)權(quán)限的使用方式,直接上代碼
配置
"AuthenticationOptions": {"AuthenticationProviderKey": "TestKey","AllowedScopes": ["admin","user"] }認(rèn)證
var result = await context.HttpContext.AuthenticateAsync(context.DownstreamReRoute.AuthenticationOptions.AuthenticationProviderKey);context.HttpContext.User = result.Principal;if (context.HttpContext.User.Identity.IsAuthenticated){await _next.Invoke(context);}權(quán)限驗證
var authorised = _scopesAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.AuthenticationOptions.AllowedScopes);從以前的代碼我們可以看出認(rèn)證授權(quán)的邏輯
1、HttpContext.AuthenticateAsync來進行認(rèn)證驗證,即驗證Jwt token的有效可用性,其中AuthenticationProviderKey為身份驗證提供程序標(biāo)識,例如
public void ConfigureServices(IServiceCollection services) { var authenticationProviderKey = "TestKey"; services.AddAuthentication().AddJwtBearer(authenticationProviderKey, x => { }); }2、當(dāng)1驗證通過后,我們可以通過context.HttpContext.User獲取key為scope的Claim數(shù)組信息(所以token生成要帶上此參數(shù)),然后與配置的AllowedScopes的數(shù)組進行交集驗證,當(dāng)交集大于0時即為有權(quán)限訪問
所以子服務(wù)如果需要實現(xiàn)和網(wǎng)關(guān)相同的權(quán)限驗證就需要實現(xiàn)以上的方式,用過net core默認(rèn)的權(quán)限認(rèn)證時會發(fā)現(xiàn),權(quán)限的驗證都需要體現(xiàn)設(shè)定好接口的可訪問角色等參數(shù),這不符合我們的需求所以我們需要實現(xiàn)一個自定義的權(quán)限認(rèn)證AuthorizationHandler,直接上代碼:
?View Code其中_permissionAuthoriser.Authorise為權(quán)限驗證方法,繼續(xù)往下看實現(xiàn)邏輯
1 public class ScopesAuthoriser : IPermissionAuthoriser 2 { 3 private readonly IPermissionRepository _permissionRepository; 4 private readonly IClaimsParser _claimsParser; 5 private readonly string _scope = "scope"; 6 private bool _loaded = false; 7 public ScopesAuthoriser(IPermissionRepository permissionRepository, IClaimsParser claimsParser) 8 { 9 _permissionRepository = permissionRepository; 10 _claimsParser = claimsParser; 11 } 12 13 public bool Authorise(HttpContext httpContext) 14 { 15 if (!_loaded && _permissionRepository.Permissions.Count == 0) 16 _permissionRepository.Get(); 17 _loaded = true; 18 19 var permission = _permissionRepository.Permissions 20 .FirstOrDefault(it => string.Equals(it.Path, httpContext.Request.Path, StringComparison.CurrentCultureIgnoreCase) && it.Method == httpContext.Request.Method); 21 22 if (permission == null) 23 return true; 24 25 var values = _claimsParser.GetValuesByClaimType(httpContext.User.Claims, _scope); 26 27 var matchesScopes = permission.Scope.Intersect(values).ToList(); 28 29 if (matchesScopes.Count == 0) 30 return false; 31 32 return true; 33 } 34 }其中_permissionRepository.Permissions是應(yīng)用的接口列表與接口對應(yīng)的可訪問scope;權(quán)限倉儲下面進行介紹
接口權(quán)限如何動態(tài)配置與修改
認(rèn)證授權(quán)數(shù)據(jù)庫設(shè)計,tb_api_resources Api資源表、tb_roles 角色表、tb_role_apis 角色Api資源關(guān)系表、tb_users 用戶表、tb_user_roles 用戶角色表
常規(guī)驗證權(quán)限方式,是根據(jù)用戶的id查詢用戶角色,然后驗證角色是否擁有接口權(quán)限;而在網(wǎng)關(guān)中是反過來該接口有哪些角色可以訪問;
所以我們需要初始化出應(yīng)用接口對應(yīng)所需角色,目前我們實現(xiàn)了mysql版本的權(quán)限倉儲IPermissionRepository的數(shù)據(jù)查詢,代碼如下
?
1 public class MySqlPermissionRepository : IPermissionRepository 2 { 3 private readonly string _dbConnectionString; 4 private readonly string _projectName; 5 6 public MySqlPermissionRepository(string dbConnectionString, string projectName) 7 { 8 _dbConnectionString = dbConnectionString; 9 _projectName = projectName; 10 } 11 public List<Permission> Permissions { get; private set; } = new List<Permission>(); 12 public async Task Get() 13 { 14 using (var dbContext = new MySqlConnection(_dbConnectionString)) 15 { 16 // 平臺下所有需要認(rèn)證Scope的接口 17 var apiList = await dbContext.QueryAsync<ApiInfo>(@"SELECT api.Url,api.Method,roleapi.RoleId 18 FROM tb_api_resources AS api 19 LEFT JOIN tb_role_apis AS roleapi ON api.Id = roleapi.ApiId 20 WHERE AllowScope = 2 AND ProjectName = @ProjectName", new { ProjectName = _projectName }); 21 // 所有角色 22 var roleList = await dbContext.QueryAsync<RoleInfo>(@"SELECT Id, `Key` from tb_roles WHERE IsDel=0", new { ProjectName = _projectName }); 23 if (apiList.Any()) 24 { 25 var permission = new List<Permission>(); 26 var apiUrlList = apiList.GroupBy(it => it.Url).Select(it => it.FirstOrDefault()).ToList(); 27 apiUrlList.ForEach(api => 28 { 29 var apiMethodList = apiList.Where(it => it.Url == api.Url).GroupBy(it => it.Method).Select(it => it.FirstOrDefault()).ToList(); 30 apiMethodList.ForEach(method => 31 { 32 var apiInfo = apiList.Where(it => it.Url == api.Url && it.Method == method.Method).FirstOrDefault(); 33 var roleids = apiList.Where(it => it.Url == api.Url && it.Method == method.Method).Select(it => it.RoleId).ToArray(); 34 var scopes = roleList.Where(it => roleids.Contains(it.Id)).Select(it => it.Key).ToList(); 35 permission.Add(new Permission 36 { 37 Path = apiInfo.Url, 38 Method = apiInfo.Method, 39 Scope = scopes 40 }); 41 }); 42 }); 43 if (permission.Count > 0) 44 Permissions = permission; 45 } 46 } 47 } 48 }這里只會實現(xiàn)一次查詢,如果中間有接口權(quán)限進行了修改,那么如何進行更新呢,在上一篇配置中間使用中,我們介紹了如何使用組件的定時任務(wù)和組件的監(jiān)聽方式,所以我們只需做對應(yīng)擴展即可,定時代碼就不貼了,監(jiān)聽代碼如下:
1 public class BucketAuthorizeListener : IBucketListener 2 { 3 private readonly IPermissionRepository _permissionRepository; 4 5 public BucketAuthorizeListener(IPermissionRepository permissionRepository) 6 { 7 _permissionRepository = permissionRepository; 8 } 9 10 public string ListenerName => "Bucket.Authorize"; 11 12 public async Task ExecuteAsync(string commandText) 13 { 14 if (!string.IsNullOrWhiteSpace(commandText) && commandText == NetworkCommandType.Reload.ToString()) 15 await _permissionRepository.Get(); 16 } 17 }下面貼一下Bucket.Authorize如何使用代碼
1 public void ConfigureServices(IServiceCollection services) 2 { 3 // 添加授權(quán) 4 services.AddApiJwtAuthorize(Configuration); 5 // 添加授權(quán)認(rèn)證 6 services.AddApiJwtAuthorize(Configuration).UseAuthoriser(services, builder => { builder.UseMySqlAuthorize(); }); 7 }然后在需要認(rèn)證授權(quán)的action或者controller加上[Authorize("permission")]屬性,appsetting配置如下,也可移至配置中心
?View Code前后端分離模式下通用的后臺管理系統(tǒng)
在FamilyBucket-UI中我們可以對項目的接口權(quán)限認(rèn)證方式、用戶、用戶角色、角色、角色權(quán)限、角色菜單等等進行配置,
同時FamilyBucket-UI還具有通用管理系統(tǒng)的基礎(chǔ)模塊,里面增加一個管理平臺的概念,可以直接多個管理平臺使用同一個用戶體系
本章就不做介紹了,內(nèi)容有點長,下次再做詳細(xì)介紹,在多平臺同時管理時項目還需要進行一些升級,截圖如下
本章涉及源碼均可在github中進行查看
https://github.com/q315523275/FamilyBucket
https://github.com/q315523275/FamilyBucket-UI?
原文地址https://www.cnblogs.com/tianxiangzhe/p/10419334.html
總結(jié)
以上是生活随笔為你收集整理的【NET CORE微服务一条龙应用】第三章 认证授权与动态权限配置的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【数道云大数据】大数据平台哪一个好用?武
- 下一篇: maxcompute 2.0复杂数据类型