[Abp vNext微服务实践] - 搭建租户管理服务

一、简介

ABP模板项目中已经提供了租户登录和管理功能,但是模板项目是单体应用结构,无法单独部署租户服务,所以难以满足微服务的需求。本篇文章将会介绍搭建ABP租户管理服务,并单独部署应用。

二、创建工程

2.1 创建TenantService.Host服务

微服务的开发应该是模块的,所以TenantService.Host服务名没有放在在ABP微服务解决方案中,选择独立搭建、独立部署的方式。

三、引用模块

在大型团队中或者小型精英团队中建议拉取将ABP源码发布本地Nuget包,所有服务引用本地包进行开发。因为无论ABP如何通用也是无法满足企业级后台业务的发展和版本迭代的,有老司机的团队应该要掌握修改ABP底层应用甚至底层框架的能力。

3.1 引用ids4、.net core、ABP等必须组件

  • Serilog.Extensions.Hosting Version="3.0.0"

  • Serilog.Sinks.File Version="4.0.0"

  • Serilog.Sinks.Elasticsearch Version="6.5.0"

  • Swashbuckle.AspNetCore Version="5.0.0-rc4"

  • IdentityServer4.AccessTokenValidation Version="3.0.0"

  • Microsoft.Extensions.Caching.StackExchangeRedis Version="3.1.0"

  • Microsoft.AspNetCore.DataProtection.StackExchangeRedis Version="3.1.0"

  • Volo.Abp.AspNetCore.MultiTenancy Version="2.0.1"

  • Volo.Abp.AuditLogging.EntityFrameworkCore Version="2.0.1"

  • Volo.Abp.Autofac Version="2.0.1"

  • Volo.Abp.EntityFrameworkCore.SqlServer Version="2.0.1"

  • Volo.Abp.EventBus.RabbitMQ Version="2.0.1"

  • Volo.Abp.PermissionManagement.EntityFrameworkCore Version="2.0.1"

  • Volo.Abp.SettingManagement.EntityFrameworkCore Version="2.0.1"

  • Volo.Abp.TenantManagement.Application Version="2.0.1"

  • Volo.Abp.TenantManagement.EntityFrameworkCore Version="2.0.1"

  • Volo.Abp.TenantManagement.HttpApi Version="2.0.1"

  • Volo.Abp.Identity.EntityFrameworkCore Version="2.0.1"

  • volo.abp.identityserver.entityframeworkcore Version="2.0.1"

四、配置Module

ABP不仅基于DDD设计,更是基于模块化实现的。

4.1 添加TenantServiceHostModule

在TenantService.Host根目录中添加TenantServiceHostModule

4.2 引用依赖

租户服务关系的ABP应用模块比较多,所以依赖也比其他服务多一些。ABP模块引用会在服务模块启动时载入IOC容器,这样的好处是无需多次引用,只要在Mudule中引用一次就可以。
引用的依赖顺序如下:
AbpAutofacModule
AbpEventBusRabbitMqModule
AbpAspNetCoreMultiTenancyModule
AbpEntityFrameworkCoreSqlServerModule
AbpAuditLoggingEntityFrameworkCoreModule
AbpPermissionManagementEntityFrameworkCoreModule
AbpSettingManagementEntityFrameworkCoreModule
AbpTenantManagementHttpApiModule
AbpTenantManagementEntityFrameworkCoreModule
AbpTenantManagementApplicationModule
AbpIdentityEntityFrameworkCoreModule
AbpIdentityServerEntityFrameworkCoreModule

4.3 注册服务

与其他服务一样需要注册认证、Swagger、默认语言、数据库服务、redis等,这里就不过多赘述了,ABP文档有详细的解释。

4.4 配置初始化模块

这里也跟其他服务一样,没有特殊的模块需要初始化。

4.5 TenantServiceHostModule完整代码如下:

Copyusing Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.OpenApi.Models;
using StackExchange.Redis;
using System.Collections.Generic;
using System.Linq;
using System.Security.Claims;
using Volo.Abp;
using Volo.Abp.AspNetCore.MultiTenancy;
using Volo.Abp.Auditing;
using Volo.Abp.AuditLogging.EntityFrameworkCore;
using Volo.Abp.Autofac;
using Volo.Abp.Data;
using Volo.Abp.EntityFrameworkCore;
using Volo.Abp.EntityFrameworkCore.SqlServer;
using Volo.Abp.EventBus.RabbitMq;
using Volo.Abp.Identity;
using Volo.Abp.Identity.EntityFrameworkCore;
using Volo.Abp.IdentityServer.EntityFrameworkCore;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.PermissionManagement.EntityFrameworkCore;
using Volo.Abp.Security.Claims;
using Volo.Abp.SettingManagement.EntityFrameworkCore;
using Volo.Abp.TenantManagement;
using Volo.Abp.TenantManagement.EntityFrameworkCore;
using Volo.Abp.Threading;namespace TenantService.Host
{[DependsOn(typeof(AbpAutofacModule),typeof(AbpEventBusRabbitMqModule),typeof(AbpAspNetCoreMultiTenancyModule),typeof(AbpEntityFrameworkCoreSqlServerModule),typeof(AbpAuditLoggingEntityFrameworkCoreModule),typeof(AbpPermissionManagementEntityFrameworkCoreModule),typeof(AbpSettingManagementEntityFrameworkCoreModule),typeof(AbpTenantManagementHttpApiModule),typeof(AbpTenantManagementEntityFrameworkCoreModule),typeof(AbpTenantManagementApplicationModule),typeof(AbpIdentityEntityFrameworkCoreModule),typeof(AbpIdentityServerEntityFrameworkCoreModule))]public class TenantServiceHostModule: AbpModule{public override void ConfigureServices(ServiceConfigurationContext context){var configuration = context.Services.GetConfiguration();context.Services.AddAuthentication("Bearer").AddIdentityServerAuthentication(options =>{options.Authority = configuration["AuthServer:Authority"];options.ApiName = configuration["AuthServer:ApiName"];options.RequireHttpsMetadata = false;});context.Services.AddSwaggerGen(options =>{options.SwaggerDoc("v1", new OpenApiInfo { Title = "Tenant Service API", Version = "v1" });options.DocInclusionPredicate((docName, description) => true);options.CustomSchemaIds(type => type.FullName);});Configure<AbpLocalizationOptions>(options =>{options.Languages.Add(new LanguageInfo("en", "en", "English"));});Configure<AbpDbContextOptions>(options =>{options.UseSqlServer();});context.Services.AddStackExchangeRedisCache(options =>{options.Configuration = configuration["Redis:Configuration"];});Configure<AbpAuditingOptions>(options =>{options.IsEnabledForGetRequests = true;options.ApplicationName = "TenantService";});var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);context.Services.AddDataProtection().PersistKeysToStackExchangeRedis(redis, "DataProtection-Keys");}public override void OnApplicationInitialization(ApplicationInitializationContext context){var app = context.GetApplicationBuilder();app.UseCorrelationId();app.UseVirtualFiles();app.UseRouting();app.UseAuthentication();app.Use(async (ctx, next) =>{var currentPrincipalAccessor = ctx.RequestServices.GetRequiredService<ICurrentPrincipalAccessor>();var map = new Dictionary<string, string>(){{ "sub", AbpClaimTypes.UserId },{ "role", AbpClaimTypes.Role },{ "email", AbpClaimTypes.Email },//any other map};var mapClaims = currentPrincipalAccessor.Principal.Claims.Where(p => map.Keys.Contains(p.Type)).ToList();currentPrincipalAccessor.Principal.AddIdentity(new ClaimsIdentity(mapClaims.Select(p => new Claim(map[p.Type], p.Value, p.ValueType, p.Issuer))));await next();});app.UseAbpRequestLocalization(); //TODO: localization?app.UseSwagger();app.UseSwaggerUI(options =>{options.SwaggerEndpoint("/swagger/v1/swagger.json", "Tenant Service API");});app.UseAuditing();app.UseMvcWithDefaultRouteAndArea();//TODO: Problem on a clustered environmentAsyncHelper.RunSync(async () =>{using (var scope = context.ServiceProvider.CreateScope()){await scope.ServiceProvider.GetRequiredService<IDataSeeder>().SeedAsync();}});}}
}

五、管理租户

5.1 启动TenantService.Host服务

Ctrl+F5启动即可,启动成功后可以看到Swagger跳转。

此时ABP已经将租户的权限种子数据添加到数据库。

5.2 添加租户

使用POST请求添加Default租户

请求成功并返回租户信息:

此时ABP已经自动添加Dfault租户的admin用户、角色和权限。

5.3 使用租户登录

在AuthServer中使用Default获取token

可以看出租户已经启用并成功登录,而且token中已经包含tenant

六、总结

ABP社区版中的租户功能有点弱,应付中小型项目是绰绰有余的,对于大型SaaS系统笔者还是建议购买商业版以获得更大的支持。ABP的租户还有更多的配置,如租户独立数据库等,在搭建成功租户服务后可以一步步尝试更多的ABP特性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/311190.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

编写高性能的C#代码(三)使用SPAN

原文来自互联网&#xff0c;由长沙DotNET技术社区编译。如译文侵犯您的署名权或版权&#xff0c;请联系小编&#xff0c;小编将在24小时内删除。作者介绍&#xff1a;史蒂夫戈登&#xff08;Steve Gordon&#xff09;是Microsoft MVP&#xff0c;Pluralsight的作者&#xff0c;…

pycharm配置git拉取项目代码,并添加版本控制

安装Git 打开网页进入git官网&#xff0c;找到git官网下载地址&#xff0c;下载git工具并且安装。 pycharm配置git 点击File -> Settings -> Version Control -> Git 选择Git安装的路径&#xff0c;点击OK 选择一个项目 进入我们需要拉取的项目&#xff0c;点击…

.NET Core开发实战(第22课:异常处理中间件:区分真异常与逻辑异常)--学习笔记(上)...

22 | 异常处理中间件&#xff1a;区分真异常与逻辑异常这一节我们来讲解一下错误处理的最佳实践系统里面异常处理&#xff0c;ASP.NET Core 提供了四种方式1、异常处理页2、异常处理匿名委托方法3、IExceptionFilter4、ExceptionFilterAttribute源码链接&#xff1a;https://gi…

MYSQL开窗函数详解

基本概念 MYSQL8.0支持窗口函数&#xff08;Window Function&#xff09;&#xff0c;也称分析函数。窗口函数与组分聚合函数类似&#xff0c;但是每一行数据都会生成一个结果。如果我们将mysql与pandas中的DataFrame做类比学习的话他们的对应关系如下&#xff1a; SQL分组聚…

你可能需要了解一下的中台

【中台学习】| 作者 / Edison Zhou这是恰童鞋骚年的第201篇原创文章在数字化转型热潮下&#xff0c;各家企业都想建设中台&#xff0c;那么中台是怎么发展起来的&#xff1f;有哪些类型的中台&#xff1f;中台到底是个啥&#xff1f;本文为你一一解答这些问题。1学习背景与前言…

github运行不流畅问题

快速流畅访问Github工具 下载链接如下&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1RwdrNK__Vx-AEuUr8sM6pg 提取码&#xff1a;a0tw –来自百度网盘超级会员V3的分享 下载后解压&#xff0c;双击运行.exe文件 运行后长这样&#xff0c;给它丢一边不管就行了。

聊聊微信的Dark模式

大家好&#xff0c;我是Z哥。这周微信公布了一个我期待已久的好消息。周一的时候对外公布说&#xff0c;已经完成了iOS版本的Dark模式开发&#xff0c;可能会在下一个版本上线。▲截图来源于微博&#xff0c;版权归原作者所有真的是千呼万唤使出来&#xff0c;很多人期待这个功…

chrome浏览器快速访问stackoverflow

原因&#xff1a;国内网非常多的网站都使用免费的 Google CDN 服务来加载某些 js、字体样式库以提升网页浏览体验&#xff0c;例如 jQuery、Google Fonts。但是目前 Google 的大多数网站在大陆无法正常访问&#xff0c;因此这些本身是加快网页载入的库反而成为了阻塞网站加载的…

【开源要闻】Canonical发布新OpenStack工具、Kubernetes访客引导方法

Canonical发布支持CephFS的OpenStack Charms 20.02Canonical近日宣布了OpenStack Charms 20.02的全面上市&#xff0c;这是用于在Ubuntu上设计&#xff0c;构建和管理OpenStack私有云的强大工具的主要版本。OpenStack Charms 20.02是一个令人兴奋的版本&#xff0c;它增加了主要…

开窗函数(1)-部门工资前三员工

已知表 题目 公司的主管们感兴趣的是公司每个部门中谁赚的钱最多。一个部门的 高收入者 是指一个员工的工资在该部门的 不同 工资中 排名前三 。 编写一个SQL查询&#xff0c;找出每个部门中 收入高的员工 。 以 任意顺序 返回结果表。 示例 参考答案 selectbase.Departmen…

Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式

一、前言上一篇我分享了一篇关于 Asp.Net Core 中IdentityServer4 授权中心之应用实战的文章&#xff0c;其中有不少博友给我提了问题&#xff0c;其中有一个博友问我的一个场景&#xff0c;我给他解答的还不够完美&#xff0c;之后我经过自己的学习查阅并阅读了相关源代码&…

缺失值处理

处理思路 在数据预处理过程中&#xff0c;难免会有数据的确实情况&#xff0c;无论是自己爬虫获取的还是从公开数据源上获取的数据集&#xff0c;都不能保证数据集是完全准确的&#xff0c;难免会有一些缺失值。而以这样数据集为基础进行建模或者数据分析时&#xff0c;缺失值…

在线教育,异军突起,有一种华丽转身,叫做.NET在线讲师!(全职/兼职皆可)...

在线教育2020年&#xff0c;注定是不平凡的一年&#xff0c;疫情来袭&#xff0c;人们只能潜伏在家&#xff0c;很多人因此没有了收入甚至没有了工作&#xff0c;各个行业&#xff0c;也正在快速升级和重新洗牌&#xff0c;这其中&#xff0c;有一个行业&#xff0c;异军突起&a…

python计算相关系数

皮尔逊相关系数 用numpy实现 import numpy as npx np.array([1, 4, 3, 5]) y np.array([1, 3, 4, 5]) pc np.corrcoef(x, y)print(pc)输出结果&#xff1a; 调用scipy.stats中的pearsonr方法 from scipy.stats import pearsonr import numpy as npx np.array([1, 4, 3,…

领域模型

领域模型是对领域内的概念类或现实世界中对象的可视化表示。又称概念模型、领域对象模型、分析对象模型。它专注于分析问题领域本身&#xff0c;发掘重要的业务领域概念&#xff0c;并建立业务领域概念之间的关系。学会了面向对象的思想&#xff0c;却依然写不出好的面向对象的…

重新定义代理的扩展性:WebAssembly在Envoy与Istio中的应用

原文&#xff1a;https://istio.io/blog/2020/wasm-announce/作者&#xff1a;CRAIG BOX, MANDAR JOG, JOHN PLEVYAK, LOUIS RYAN, PIOTR SIKORA (GOOGLE), YUVAL KOHAVI, SCOTT WEISS (SOLO.IO)译者&#xff1a;陆培尔编者按Istio的架构在1.5版本中发生了翻天覆地的变化&#…

2019年第十届蓝桥杯国赛B组试题E-路径计数-dfs(坑题)

【问题描述】 从一个 5 x 5 的方格矩阵的左上角出发&#xff0c;沿着方格的边走&#xff0c;满足以下条件的路线有多少种&#xff1f; 总长度不超过 12&#xff1b; 最后回到左上角&#xff1b; 路线不自交&#xff1b; 不走出 5 x 5 的方格矩阵范围之外。如下图所示&#xff…

.NET Core开发实战(第22课:异常处理中间件:区分真异常与逻辑异常)--学习笔记(下)...

接下来介绍使用代理方法的方式&#xff0c;也就是说把 ErrorController 整段逻辑直接定义在注册的地方&#xff0c;使用一个匿名委托来处理&#xff0c;这里的逻辑与之前的逻辑是相同的app.UseExceptionHandler(errApp > {errApp.Run(async context >{// 在 Features 里面…

【朝夕技术专刊】Core3.1WebApi_Filter-Authorize详解

欢迎大家阅读《朝夕Net社区技术专刊》第6期我们致力于.NetCore的推广和落地&#xff0c;为更好的帮助大家学习&#xff0c;方便分享干货&#xff0c;特创此刊&#xff01;很高兴你能成为忠实读者&#xff0c;文末福利不要错过哦&#xff01;前言&#xff1a;本部分文档将详细给…

以正确的方式下载和配置 ASP.NET Core 官方源码

我们可以在Github上面直接查看ASP.NETCore 3.x的源代码&#xff0c;但是我们也可以把源代码下载下来进行查看。而下载源代码进行查看有很多好处&#xff1a;任意的导航源代码内置了一个示例项目直接调试源代码下载源代码想下载并配置好源码&#xff0c;你需要&#xff1a;最新版…