【NET CORE微服务一条龙应用】第三章 认证授权与动态权限配置
【NET CORE微服務(wù)一條龍應(yīng)用】第三章 認(rèn)證授權(quán)與動(dòng)態(tài)權(quán)限配置
介紹
系列目錄:【NET CORE微服務(wù)一條龍應(yīng)用】開(kāi)始篇與目錄
在微服務(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ù)如何實(shí)現(xiàn)和網(wǎng)關(guān)相同的鑒權(quán)方式
2、接口權(quán)限如何動(dòng)態(tài)配置與修改
3、前后端分離模式下通用的后臺(tái)管理系統(tǒng)(用戶、權(quán)限、菜單、平臺(tái))
需提前了解知識(shí)點(diǎ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)限驗(yàn)證
var authorised = _scopesAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.AuthenticationOptions.AllowedScopes);從以前的代碼我們可以看出認(rèn)證授權(quán)的邏輯
1、HttpContext.AuthenticateAsync來(lái)進(jìn)行認(rèn)證驗(yàn)證,即驗(yàn)證Jwt token的有效可用性,其中AuthenticationProviderKey為身份驗(yàn)證提供程序標(biāo)識(shí),例如
public void ConfigureServices(IServiceCollection services) { var authenticationProviderKey = "TestKey"; services.AddAuthentication().AddJwtBearer(authenticationProviderKey, x => { }); }2、當(dāng)1驗(yàn)證通過(guò)后,我們可以通過(guò)context.HttpContext.User獲取key為scope的Claim數(shù)組信息(所以token生成要帶上此參數(shù)),然后與配置的AllowedScopes的數(shù)組進(jìn)行交集驗(yàn)證,當(dāng)交集大于0時(shí)即為有權(quán)限訪問(wèn)
所以子服務(wù)如果需要實(shí)現(xiàn)和網(wǎng)關(guān)相同的權(quán)限驗(yàn)證就需要實(shí)現(xiàn)以上的方式,用過(guò)net core默認(rèn)的權(quán)限認(rèn)證時(shí)會(huì)發(fā)現(xiàn),權(quán)限的驗(yàn)證都需要體現(xiàn)設(shè)定好接口的可訪問(wèn)角色等參數(shù),這不符合我們的需求所以我們需要實(shí)現(xiàn)一個(gè)自定義的權(quán)限認(rèn)證AuthorizationHandler,直接上代碼:
?View Code其中_permissionAuthoriser.Authorise為權(quán)限驗(yàn)證方法,繼續(xù)往下看實(shí)現(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)用的接口列表與接口對(duì)應(yīng)的可訪問(wèn)scope;權(quán)限倉(cāng)儲(chǔ)下面進(jìn)行介紹
接口權(quán)限如何動(dòng)態(tài)配置與修改
認(rèn)證授權(quán)數(shù)據(jù)庫(kù)設(shè)計(jì),tb_api_resources Api資源表、tb_roles 角色表、tb_role_apis 角色Api資源關(guān)系表、tb_users 用戶表、tb_user_roles 用戶角色表
常規(guī)驗(yàn)證權(quán)限方式,是根據(jù)用戶的id查詢用戶角色,然后驗(yàn)證角色是否擁有接口權(quán)限;而在網(wǎng)關(guān)中是反過(guò)來(lái)該接口有哪些角色可以訪問(wèn);
所以我們需要初始化出應(yīng)用接口對(duì)應(yīng)所需角色,目前我們實(shí)現(xiàn)了mysql版本的權(quán)限倉(cāng)儲(chǔ)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 // 平臺(tái)下所有需要認(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 }這里只會(huì)實(shí)現(xiàn)一次查詢,如果中間有接口權(quán)限進(jìn)行了修改,那么如何進(jìn)行更新呢,在上一篇配置中間使用中,我們介紹了如何使用組件的定時(shí)任務(wù)和組件的監(jiān)聽(tīng)方式,所以我們只需做對(duì)應(yīng)擴(kuò)展即可,定時(shí)代碼就不貼了,監(jiān)聽(tīng)代碼如下:
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ái)管理系統(tǒng)
在FamilyBucket-UI中我們可以對(duì)項(xiàng)目的接口權(quán)限認(rèn)證方式、用戶、用戶角色、角色、角色權(quán)限、角色菜單等等進(jìn)行配置,
同時(shí)FamilyBucket-UI還具有通用管理系統(tǒng)的基礎(chǔ)模塊,里面增加一個(gè)管理平臺(tái)的概念,可以直接多個(gè)管理平臺(tái)使用同一個(gè)用戶體系
本章就不做介紹了,內(nèi)容有點(diǎn)長(zhǎng),下次再做詳細(xì)介紹,在多平臺(tái)同時(shí)管理時(shí)項(xiàng)目還需要進(jìn)行一些升級(jí),截圖如下
本章涉及源碼均可在github中進(jìn)行查看
https://github.com/q315523275/FamilyBucket
https://github.com/q315523275/FamilyBucket-UI?
原文地址https://www.cnblogs.com/tianxiangzhe/p/10419334.html
總結(jié)
以上是生活随笔為你收集整理的【NET CORE微服务一条龙应用】第三章 认证授权与动态权限配置的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【数道云大数据】大数据平台哪一个好用?武
- 下一篇: maxcompute 2.0复杂数据类型