【NET CORE微服务一条龙应用】第三章 认证授权与动态权限配置

本文涉及的产品
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 【NET CORE微服务一条龙应用】第三章 认证授权与动态权限配置 介绍 系列目录:【NET CORE微服务一条龙应用】开始篇与目录 在微服务的应用中,统一的认证授权是必不可少的组件,本文将介绍微服务中网关和子服务如何使用统一的权限认证 主要介绍内容为: 1、子服务如何实现和网关相同的鉴权方式 2.

【NET CORE微服务一条龙应用】第三章 认证授权与动态权限配置

介绍

系列目录:【NET CORE微服务一条龙应用】开始篇与目录

在微服务的应用中,统一的认证授权是必不可少的组件,本文将介绍微服务中网关和子服务如何使用统一的权限认证

主要介绍内容为:

1、子服务如何实现和网关相同的鉴权方式

2、接口权限如何动态配置与修改

3、前后端分离模式下通用的后台管理系统(用户、权限、菜单、平台)

需提前了解知识点:

1、Jwt (JSON Web Token)

2、ClaimsPrincipal

3、Microsoft.AspNetCore.Authorization、AuthorizationPolicy、AuthorizationHandler

子服务和网关鉴权方式

首先我们需要了解一下Ocelot网关权限的使用方式,直接上代码

配置

"AuthenticationOptions": {
    "AuthenticationProviderKey": "TestKey",
    "AllowedScopes": ["admin","user"]
}

认证

复制代码
 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);
 }
复制代码

权限验证

var authorised = _scopesAuthoriser.Authorise(context.HttpContext.User, context.DownstreamReRoute.AuthenticationOptions.AllowedScopes);

从以前的代码我们可以看出认证授权的逻辑

1、HttpContext.AuthenticateAsync来进行认证验证,即验证Jwt token的有效可用性,其中AuthenticationProviderKey为身份验证提供程序标识,例如

public void ConfigureServices(IServiceCollection services) { var authenticationProviderKey = "TestKey"; services.AddAuthentication().AddJwtBearer(authenticationProviderKey, x => { }); }

2、当1验证通过后,我们可以通过context.HttpContext.User获取key为scope的Claim数组信息(所以token生成要带上此参数),然后与配置的AllowedScopes的数组进行交集验证,当交集大于0时即为有权限访问

所以子服务如果需要实现和网关相同的权限验证就需要实现以上的方式,用过net core默认的权限认证时会发现,权限的验证都需要体现设定好接口的可访问角色等参数,这不符合我们的需求所以我们需要实现一个自定义的权限认证AuthorizationHandler,直接上代码:

  View Code

其中_permissionAuthoriser.Authorise为权限验证方法,继续往下看实现逻辑

复制代码
 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是应用的接口列表与接口对应的可访问scope;权限仓储下面进行介绍

接口权限如何动态配置与修改

认证授权数据库设计,tb_api_resources Api资源表、tb_roles 角色表、tb_role_apis 角色Api资源关系表、tb_users 用户表、tb_user_roles 用户角色表

常规验证权限方式,是根据用户的id查询用户角色,然后验证角色是否拥有接口权限;而在网关中是反过来该接口有哪些角色可以访问;

所以我们需要初始化出应用接口对应所需角色,目前我们实现了mysql版本的权限仓储IPermissionRepository的数据查询,代码如下

 

复制代码
 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                 // 平台下所有需要认证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     }
复制代码

这里只会实现一次查询,如果中间有接口权限进行了修改,那么如何进行更新呢,在上一篇配置中间使用中,我们介绍了如何使用组件的定时任务和组件的监听方式,所以我们只需做对应扩展即可,定时代码就不贴了,监听代码如下:

复制代码
 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             // 添加授权
4             services.AddApiJwtAuthorize(Configuration);
5             // 添加授权认证
6             services.AddApiJwtAuthorize(Configuration).UseAuthoriser(services, builder => { builder.UseMySqlAuthorize(); });
7         }
复制代码

然后在需要认证授权的action或者controller加上[Authorize("permission")]属性,appsetting配置如下,也可移至配置中心

  View Code

前后端分离模式下通用的后台管理系统

在FamilyBucket-UI中我们可以对项目的接口权限认证方式、用户、用户角色、角色、角色权限、角色菜单等等进行配置,

同时FamilyBucket-UI还具有通用管理系统的基础模块,里面增加一个管理平台的概念,可以直接多个管理平台使用同一个用户体系

本章就不做介绍了,内容有点长,下次再做详细介绍,在多平台同时管理时项目还需要进行一些升级,截图如下

本章涉及源码均可在github中进行查看

https://github.com/q315523275/FamilyBucket

https://github.com/q315523275/FamilyBucket-UI 

原文地址https://www.cnblogs.com/tianxiangzhe/p/10419334.html

相关实践学习
基于CentOS快速搭建LAMP环境
本教程介绍如何搭建LAMP环境,其中LAMP分别代表Linux、Apache、MySQL和PHP。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
1天前
|
开发框架 JSON .NET
.Net4.0 Web.config 配置实践
.Net4.0 Web.config 配置实践
|
2天前
|
监控 负载均衡 API
微服务架构在现代企业中的应用与挑战
微服务架构已成为现代企业构建灵活且可扩展软件系统的首选。然而,随着其应用的普及,企业也面临着一系列新的挑战。本篇文章将探讨微服务架构的优势、实施时遇到的问题以及解决这些问题的策略。
|
2天前
|
Kubernetes Cloud Native 持续交付
构建高效云原生应用:Kubernetes与微服务架构的融合
【5月更文挑战第6天】 在数字化转型的浪潮中,企业正迅速采纳云原生技术以实现敏捷性、可扩展性和弹性。本文深入探讨了如何利用Kubernetes这一领先的容器编排平台,结合微服务架构,构建和维护高效、可伸缩的云原生应用。通过分析现代软件设计原则和最佳实践,我们提出了一个综合指南,旨在帮助开发者和系统架构师优化云资源配置,提高部署流程的自动化水平,并确保系统的高可用性。
22 1
|
6天前
|
C# Windows
一款.NET开源、简洁易用的Windows桌面小说阅读应用
一款.NET开源、简洁易用的Windows桌面小说阅读应用
|
8天前
|
消息中间件 PHP 数据库
【PHP开发专栏】PHP在微服务架构中的应用
【4月更文挑战第29天】微服务架构将大型应用拆分成独立小服务,PHP在其中可作为API网关、微服务提供者,参与服务发现、消息队列处理和事件驱动。最佳实践包括选择合适PHP框架、使用容器化技术、定义服务契约、采用分布式缓存、实现服务发现、监控和日志收集、优化数据库设计以及注重安全性。遵循这些实践,PHP开发者能构建高效、可扩展的微服务应用。
|
8天前
|
开发框架 物联网 测试技术
【专栏】.NET 开发:打造领先应用的基石
【4月更文挑战第29天】本文探讨了.NET开发框架为何成为构建领先应用的首选。高性能与稳定性是.NET的核心优势,它采用先进的技术和优化策略,如.NET Core的轻量级设计和JIT/AOT编译模式。跨平台兼容性让开发者能用相同代码库在不同操作系统上构建应用。现代化的开发体验,如C#语言的创新特性和Visual Studio的强大工具,提升了开发者生产力。丰富的生态系统和广泛支持,包括庞大的开发者社区和微软的持续投入,为.NET提供了坚实后盾。
|
8天前
|
机器学习/深度学习 人工智能 Cloud Native
【专栏】洞察.NET 技术的前沿应用
【4月更文挑战第29天】本文探讨了.NET技术的前沿应用,包括.NET Core的跨平台崛起、云原生及AI/机器学习领域的整合。.NET Core支持多平台运行,开源社区的参与促进了其快速发展和性能优化。Xamarin与.NET MAUI助力跨平台移动应用和统一界面开发,而云原生应用借助.NET Core与Azure云服务得以轻松构建和部署。此外,ML.NET和TensorFlow.NET为.NET开发者提供了机器学习和深度学习工具,推动智能应用和边缘计算的创新。.NET技术正持续演进,引领软件开发新趋势。
|
8天前
|
人工智能 物联网 开发者
【专栏】探究.NET 技术的创新应用
【4月更文挑战第29天】本文探讨了.NET技术的最新进展和创新应用,包括.NET 5及后续版本的统一平台、性能提升、跨平台支持、云集成优化和开源社区的贡献。在创新应用场景中,重点介绍了微服务架构、物联网、AI、游戏开发和移动应用。未来,.NET将持续优化性能,深化云原生应用,集成新兴技术,扩大社区生态,并促进相关教育和培训。开发者应把握.NET技术的潜力,积极参与其发展,创造更多创新软件产品。
|
8天前
|
安全 Linux API
【专栏】.NET 开发:打造卓越应用的秘诀
【4月更文挑战第29天】本文介绍了.NET技术的起源、核心特性和应用场景,揭示了其打造卓越应用的秘诀。自2002年推出,.NET历经发展,现支持跨平台,包括.NET Core和.NET 5。其核心特性包括:跨平台兼容性、面向对象编程、内置安全性和高效性能。丰富的类库、强大的开发工具、简洁的语言语法以及活跃的社区支持,使.NET成为构建高效、安全应用的理想选择。随着技术进步,.NET将持续赋能开发者创造更多可能性。
|
8天前
|
人工智能 安全 API
【专栏】理解 .NET 技术,打造优质应用
【4月更文挑战第29天】本文探讨了如何利用.NET技术构建高质量应用程序,介绍了.NET从2002年发展至今的历程,强调其跨平台能力、高效开发、丰富的类库和API、开源生态及安全性等优势。随着.NET 6的规划,平台将更加统一和跨平台,适应云计算、AI等新兴技术。.NET凭借其特性,成为开发者和企业创新的有力工具,未来将继续扮演重要角色。