迁移微服务应用到 OpenIddict 指南
本指南为将您现有的微服务应用迁移到 OpenIddict 提供指导。由于 OpenIddict 仅在 ABP v6.0 中可用,您需要更新现有应用才能应用 OpenIddict 变更。
历史背景
我们不会移除 Identity Server 包,并且将继续发布与 IdentityServer 相关的 NuGet/NPM 包的新版本。这意味着当稳定版发布时,您在升级到 v6.0 时不会遇到问题。我们还将继续在一段时间内修复我们包中的错误。ABP 7.0 将基于 .NET 7。如果 Identity Server 继续与 .NET 7 兼容,我们也将继续为我们的 IDS 集成提供 NuGet 包。
另一方面,Identity Server 团队在 2022 年底结束了对开源 Identity Server 的支持。Identity Server 团队已决定转向 Duende IDS,而 ABP 将不会迁移到商业版的 Duende IDS。您可以通过此链接查看 Duende Identity Server 的公告。
OpenIddict 迁移步骤
使用 abp update 命令更新您现有的应用。更多信息请参见升级文档。根据您的应用版本,按照迁移指南应用所需的迁移。
认证服务器 (AuthServer) 应用
在 MyApplication.AuthServer.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.Account.Pro.Public.Web.IdentityServer" Version="6.0.*" /> <PackageReference Include="Volo.Abp.AspNetCore.Authentication.JwtBearer" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.Account.Pro.Public.Web.OpenIddict" Version="6.0.*" />在 MyApplicationAuthServerModule.cs 中,替换 using 语句和 模块依赖:
using IdentityServer4.Extensions; using Volo.Abp.IdentityServer; ... typeof(AbpAspNetCoreAuthenticationJwtBearerModule) typeof(AbpAccountPublicWebIdentityServerModule)替换为
using Volo.Abp.OpenIddict; ... typeof(AbpAccountPublicWebOpenIddictModule),在 MyApplicationAuthServerModule.cs 中,按如下方式更新 PreConfigureServices 方法:
public override void PreConfigureServices(ServiceConfigurationContext context) { var hostingEnvironment = context.Services.GetHostingEnvironment(); var configuration = context.Services.GetConfiguration(); PreConfigure<OpenIddictBuilder>(builder => { builder.AddValidation(options => { options.AddAudiences("AccountService"); options.UseLocalServer(); options.UseAspNetCore(); }); }); if (!hostingEnvironment.IsDevelopment()) { PreConfigure<AbpOpenIddictAspNetCoreOptions>(options => { options.AddDevelopmentEncryptionAndSigningCertificate = false; }); PreConfigure<OpenIddictServerBuilder>(builder => { builder.AddSigningCertificate(GetSigningCertificate(hostingEnvironment, configuration)); builder.AddEncryptionCertificate(GetSigningCertificate(hostingEnvironment, configuration)); }); } }在 MyApplicationAuthServerModule.cs 中,移除 JwtBearer 认证选项:
context.Services.AddAuthentication() // 移除此配置 .AddJwtBearer(options => { options.Authority = configuration["AuthServer:Authority"]; options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); options.Audience = "AccountService"; });在 MyApplicationAuthServerModule.cs 的
OnApplicationInitialization方法中,替换 IdentityServer 和 JwtToken 中间件:app.UseJwtTokenMiddleware(); app.UseIdentityServer();替换为
app.UseAbpOpenIddictValidation();要使用新的 AuthServer 页面,请将 Index.cshtml.cs 替换为 AuthServer Index.cshtml.cs,并将 Index.cshtml 文件替换为 AuthServer Index.cshtml。
注意:这些文件位于 Pages 文件夹下。
AdministrationService 领域层
在 MyApplication.AdministrationService.Domain.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.IdentityServer" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.PermissionManagement.Domain.OpenIddict" Version="6.0.*" />在 MyApplicationDomainSharedModule.cs 中,替换 using 语句和 模块依赖:
using Volo.Abp.PermissionManagement.IdentityServer; ... typeof(AbpPermissionManagementDomainIdentityServerModule)替换为
using Volo.Abp.PermissionManagement.OpenIddict; ... typeof(AbpPermissionManagementDomainOpenIddictModule)
IdentityService 领域共享层
在 MyApplication.IdentityService.Domain.Shared.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.IdentityServer.Domain.Shared" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.OpenIddict.Domain.Shared" Version="6.0.*" />在 MyApplicationDomainModule.cs 中,替换 using 语句和 模块依赖:
using Volo.Abp.IdentityServer; ... typeof(AbpIdentityServerDomainModule)替换为
using Volo.Abp.OpenIddict; ... typeof(AbpOpenIddictDomainModule)
IdentityService 领域层
在 MyApplication.IdentityService.Application.Contracts.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.IdentityServer.Domain" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.OpenIddict.Domain" Version="6.0.*" />在 IdentityServiceDomainModule.cs 中,替换 using 语句和 模块依赖:
using Volo.Abp.IdentityServer; ... typeof(AbpIdentityServerDomainSharedModule)替换为
using Volo.Abp.OpenIddict; ... typeof(AbpOpenIddictDomainSharedModule)
IdentityService 应用合约层
在 MyApplication.IdentityService.Application.Contracts.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.IdentityServer.Application.Contracts" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.OpenIddict.Pro.Application.Contracts" Version="6.0.*" />在 IdentityServiceApplicationContractsModule.cs 中,替换 using 语句和 模块依赖:
using Volo.Abp.IdentityServer; ... typeof(AbpIdentityServerApplicationContractsModule)替换为
using Volo.Abp.OpenIddict; ... typeof(AbpOpenIddictProApplicationContractsModule)
IdentityService 应用层
在 MyApplication.IdentityService.Application.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.IdentityServer.Application" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.OpenIddict.Pro.Application" Version="6.0.*" />在 IdentityServiceApplicationModule.cs 中,替换 using 语句和 模块依赖:
using Volo.Abp.IdentityServer; ... typeof(AbpIdentityServerApplicationModule)替换为
using Volo.Abp.OpenIddict; ... typeof(AbpOpenIddictProApplicationModule)
IdentityService 实体框架核心层
在 MyApplication.IdentityService.EntityFrameworkCore.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.IdentityServer.EntityFrameworkCore" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.OpenIddict.EntityFrameworkCore" Version="6.0.*" />在 IdentityServiceEntityFrameworkCoreModule.cs 中,替换 using 语句和 模块依赖:
using Volo.Abp.IdentityServer.EntityFrameworkCore; ... typeof(AbpIdentityServerEntityFrameworkCoreModule),替换为
using Volo.Abp.OpenIddict.EntityFrameworkCore; ... typeof(AbpOpenIddictEntityFrameworkCoreModule),在 IdentityServiceEntityFrameworkCoreModule.cs 中,替换
AddAbpDbContext选项:options.ReplaceDbContext<IIdentityServerDbContext>();替换为
options.ReplaceDbContext<IOpenIddictDbContext>();在 IdentityServiceDbContext.cs 中,替换已实现的 DbContext:
public class IdentityServiceDbContext : AbpDbContext<IdentityServiceDbContext>, IIdentityDbContext, IIdentityServerDbContext替换为
public class IdentityServiceDbContext : AbpDbContext<IdentityServiceDbContext>, IIdentityDbContext, IOpenIddictDbContext之后,您应该拥有如下的 DbSets:
public class IdentityServiceDbContext : AbpDbContext<IdentityServiceDbContext>, IIdentityDbContext, IOpenIddictDbContext { public DbSet<IdentityUser> Users { get; set; } public DbSet<IdentityRole> Roles { get; set; } public DbSet<IdentityClaimType> ClaimTypes { get; set; } public DbSet<OrganizationUnit> OrganizationUnits { get; set; } public DbSet<IdentitySecurityLog> SecurityLogs { get; set; } public DbSet<IdentityLinkUser> LinkUsers { get; set; } public DbSet<OpenIddictApplication> Applications { get; set; } public DbSet<OpenIddictAuthorization> Authorizations { get; set; } public DbSet<OpenIddictScope> Scopes { get; set; } public DbSet<OpenIddictToken> Tokens { get; set; } }在 IdentityServiceDbContext.cs 中,替换 using 语句和 Fluent API 配置:
using Volo.Abp.IdentityServer.EntityFrameworkCore; ... using Volo.Abp.OpenIddict.EntityFrameworkCore; ... protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); /* 将模块包含到您的迁移数据库上下文中 */ builder.ConfigureIdentityPro(); builder.ConfigureIdentityServer();替换为
using Volo.Abp.OpenIddict.EntityFrameworkCore; ... protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); /* 将模块包含到您的迁移数据库上下文中 */ builder.ConfigureIdentityPro(); builder.ConfigureOpenIddict();
不要忘记使用
dotnet ef命令创建新的迁移。
IdentityService HttpApi 层
在 MyApplication.IdentityService.HttpApi.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.IdentityServer.HttpApi" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.OpenIddict.Pro.HttpApi" Version="6.0.*" />在 IdentityServiceHttpApiModule.cs 中,替换 using 语句和 模块依赖:
using Volo.Abp.IdentityServer; ... typeof(AbpIdentityServerHttpApiModule),替换为
using Volo.Abp.OpenIddict; ... typeof(AbpOpenIddictProHttpApiModule),
IdentityService HttpApi.Client 层
在 MyApplication.IdentityService.HttpApi.Client.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.IdentityServer.HttpApi.Client" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.OpenIddict.Pro.HttpApi.Client" Version="6.0.*" />在 IdentityServiceHttpApiClientModule.cs 中,替换 using 语句和 模块依赖:
using Volo.Abp.IdentityServer; ... typeof(AbpIdentityServerHttpApiClientModule),替换为
using Volo.Abp.OpenIddict; ... typeof(AbpOpenIddictProHttpApiClientModule),
IdentityServer 数据种子设定
建议更新 MyApplication.IdentityService.HttpApi.Host 项目中 DbMigrations 文件夹下的 IdentityServerDataSeeder.cs。
使用 更新后的 IdentityServerDataSeeder 来更新您现有的 IdentityServer 数据种子设定器。将 Acme.BookStore 命名空间替换为您的应用程序命名空间。
在 appsettings.json 中,将 IdentityServer 部分替换为 OpenIddict,并将 Clients 替换为 Applications。您应该得到类似以下的内容:
"OpenIddict": {
"Applications": {
"MyApplication_Web": {
"ClientId": "MyApplication_Web",
"ClientSecret": "1q2w3e*",
"RootUrl": "https://localhost:44384/"
},
...
}
}
如果您使用 DbMigrator,则应在 DbMigrator 项目下的
IdentityServerDataSeeder和 appsettings.json 中进行相同的更改。
注意:别忘了在根 URL 的末尾加上斜杠
/。
IdentityService Web 层
在 MyApplication.IdentityService.HttpApi.Client.csproj 中,将 项目引用:
<PackageReference Include="Volo.Abp.IdentityServer.Web" Version="6.0.*" />替换为
<PackageReference Include="Volo.Abp.OpenIddict.Pro.Web" Version="6.0.*" />在 IdentityServiceWebModule.cs 中,替换 using 语句和 模块依赖:
using Volo.Abp.IdentityServer.Web; ... typeof(AbpIdentityServerWebModule),替换为
using Volo.Abp.OpenIddict.Pro.Web; ... typeof(AbpOpenIddictProWebModule),在 IdentityServiceWebModule.cs 中,为 Mapperly 添加对象映射配置(如果您使用其他映射提供程序,请参阅对象到对象映射文档):
context.Services.AddMapperlyObjectMapper<IdentityServiceWebModule>();
共享宿主模块
在 MyApplicationSharedHostingModule 中,替换 数据库配置:
options.Databases.Configure("IdentityService", database => { database.MappedConnections.Add("AbpIdentity"); database.MappedConnections.Add("AbpIdentityServer"); });替换为
options.Databases.Configure("IdentityService", database => { database.MappedConnections.Add("AbpIdentity"); database.MappedConnections.Add("OpenIddict"); });
公共 Web 应用
在 AddAbpOpenIdConnect 配置选项中,将 options.Scope.Add("role"); 更新为 options.Scope.Add("roles");。
后台办公应用
根据您选择的 UI,需要像在公共 Web 应用中一样更新 OpenIdConnect 选项。将 role 作用域更新为 roles。
要更新菜单,请导航到 MyApplicationMenuContributor.cs(或 NavigationContributor)并替换菜单名称:
using Volo.Abp.IdentityServer.Web.Navigation;
...
//Administration->Identity Server
administration.SetSubItemOrder(AbpIdentityServerMenuNames.GroupName, 2);
替换为
using Volo.Abp.OpenIddict.Pro.Web.Menus;
...
//Administration->OpenIddict
administration.SetSubItemOrder(OpenIddictProMenus.GroupName, 2);
抠丁客


