迁移到 OpenIddict 4.0
有哪些新变化?
4.0 版本中最重要的变化可以在 这里 找到。
除非你正在使用 MongoDB,迁移到 OpenIddict 4.0 不需要对数据库做出更改。
更新你的包引用
为此,请更新你的 .csproj
文件以引用 OpenIddict 4.x 版本的包。例如:
<ItemGroup>
<!-- OpenIddict 3.x: -->
<PackageReference Include="OpenIddict.AspNetCore" Version="3.1.1" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="3.1.1" />
<!-- OpenIddict 4.x: -->
<PackageReference Include="OpenIddict.AspNetCore" Version="4.10.1" />
<PackageReference Include="OpenIddict.EntityFrameworkCore" Version="4.10.1" />
</ItemGroup>
迁移到 ASP.NET Core 7.0 并非必要,因为 OpenIddict 4.0 依然原生兼容 ASP.NET Core 2.1(仅限 .NET Framework)、ASP.NET Core 3.1 和 ASP.NET Core 6.0。迁移到更新的 .NET 运行时或 ASP.NET Core 可以单独进行,以便进行更简单/解耦的升级:
Web 框架版本 | .NET 运行时版本 |
---|---|
ASP.NET Core 2.1 | .NET Framework 4.6.1 |
ASP.NET Core 2.1 | .NET Framework 4.7.2 |
ASP.NET Core 2.1 | .NET Framework 4.8 |
ASP.NET Core 3.1 | .NET Core 3.1 |
ASP.NET Core 6.0 | .NET 6.0 |
ASP.NET Core 7.0 | .NET 7.0 |
Microsoft.Owin 4.2 | .NET Framework 4.6.1 |
Microsoft.Owin 4.2 | .NET Framework 4.7.2 |
Microsoft.Owin 4.2 | .NET Framework 4.8 |
更新你的端点 URI
OpenIddict 4.0 引入了一个行为变化,影响端点 URI 的计算和解析方式。关于这一变化的更多信息,请阅读 OpenIddict 4.0 中影响 URI 处理的破坏性变化 。
在大多数情况下,调整你的代码应仅限于删除端点路径中的前导斜杠,以适应新的逻辑:
services.AddOpenIddict()
.AddServer(options =>
{
// OpenIddict 3.x:
options.SetAuthorizationEndpointUris("/connect/authorize")
.SetDeviceEndpointUris("/connect/device")
.SetIntrospectionEndpointUris("/connect/introspect")
.SetLogoutEndpointUris("/connect/logout")
.SetTokenEndpointUris("/connect/token")
.SetUserinfoEndpointUris("/connect/userinfo")
.SetVerificationEndpointUris("/connect/verify");
// OpenIddict 4.x:
options.SetAuthorizationEndpointUris("connect/authorize")
.SetDeviceEndpointUris("connect/device")
.SetIntrospectionEndpointUris("connect/introspect")
.SetLogoutEndpointUris("connect/logout")
.SetTokenEndpointUris("connect/token")
.SetUserinfoEndpointUris("connect/userinfo")
.SetVerificationEndpointUris("connect/verify");
});
移除指定目标列表的 AddClaim(s)调用:
正如 OpenIddict 4.0 预览版 1 发布 中解释的那样,接受 destinations
参数的 AddClaim(s)
扩展方法在 4.0 中已被移除。
相反,建议开发者使用针对 ClaimsIdentity
和 ClaimsPrincipal
的新一键式 SetDestinations()
扩展方法(该方法必须在所有声明被添加到身份/主体之后调用)。
var identity = new ClaimsIdentity(
authenticationType: TokenValidationParameters.DefaultAuthenticationType,
nameType: Claims.Name,
roleType: Claims.Role);
identity.SetClaim(Claims.Subject, await _userManager.GetUserIdAsync(user))
.SetClaim(Claims.Email, await _userManager.GetEmailAsync(user))
.SetClaim(Claims.Name, await _userManager.GetUserNameAsync(user))
.SetClaims(Claims.Role, (await _userManager.GetRolesAsync(user)).ToImmutableArray());
identity.SetScopes(result.Principal.GetScopes());
identity.SetResources(await _scopeManager.ListResourcesAsync(identity.GetScopes()).ToListAsync());
identity.SetDestinations(static claim => claim.Type switch
{
// 允许“name”声明在访问令牌和身份令牌中存储,当授予了 “profile” 作用域(通过调用principal.SetScopes(...)实现
Claims.Name when claim.Subject.HasScope(Scopes.Profile)
=> [Destinations.AccessToken, Destinations.IdentityToken],
// 如果不满足上述条件,仅在访问令牌中存储该声明
_ => [Destinations.AccessToken]
});
如适用,请更新你的 OpenIddict MongoDB 授权
为了与其他属性使用的大小写相匹配,OpenIddictMongoDbAuthorization.CreationDate
属性在 BSON 表示中的名称已修复为使用驼峰命名法(即 creation_date
而不是 CreationDate
)。为了确保现有授权正确更新以使用新名称,可以使用以下脚本非常高效地一次性更新所有现有授权:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using OpenIddict.MongoDb;
var services = new ServiceCollection();
services.AddOpenIddict()
.AddCore()
.UseMongoDb()
.UseDatabase(new MongoClient("mongodb://localhost:27017").GetDatabase("openiddict"));
await using var provider = services.BuildServiceProvider();
var context = provider.GetRequiredService<IOpenIddictMongoDbContext>();
var options = provider.GetRequiredService<IOptionsMonitor<OpenIddictMongoDbOptions>>().CurrentValue;
var database = await context.GetDatabaseAsync(CancellationToken.None);
var authorizations = database.GetCollection<BsonDocument>(options.AuthorizationsCollectionName);
await authorizations.UpdateManyAsync(
filter: Builders<BsonDocument>.Filter.Empty,
update: Builders<BsonDocument>.Update.Rename("CreationDate", "creation_date"));
如适用,请将对 Portable.BouncyCastle 的引用替换为 BouncyCastle.Cryptography
虽然 OpenIddict 的早期版本使用了由 Claire Novotny 维护的非官方 Portable.BouncyCastle 包(这在当时是最佳的.NET Standard 兼容选项),但 OpenIddict 4.0 已更新为使用官方包 BouncyCastle.Cryptography ,该包于 2022 年 11 月发布,完全支持.NET Standard 2.0。
如果您的应用程序使用了 Portable.BouncyCastle
,强烈建议迁移到 BouncyCastle.Cryptography
以避免类型冲突。
如适用,请更新自定义存储以使用更新后的签名
OpenIddict 4.x 修正了 IOpenIddictApplicationStore.GetAsync()
、IOpenIddictAuthorizationStore.GetAsync()
、IOpenIddictScopeStore.GetAsync()
和 IOpenIddictTokenStore.GetAsync()
的可空性注解,使其返回 ValueTask<T>
而非 ValueTask<T>?
。
实现了这些接口并且启用了可空引用的开发者应被邀请更新 GetAsync()
方法的签名,以匹配这些更改:
// OpenIddict 3.x:
ValueTask<TResult> GetAsync<TState, TResult>(
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken);
// OpenIddict 4.x:
ValueTask<TResult?> GetAsync<TState, TResult>(
Func<IQueryable<TApplication>, TState, IQueryable<TResult>> query,
TState state, CancellationToken cancellationToken);
尽管不是必需的,但也建议更新 IOpenIddictApplicationStore
的实现,以使用针对 FindByPostLogoutRedirectUriAsync()
、FindByRedirectUriAsync()
、SetPostLogoutRedirectUrisAsync()
和 SetRedirectUrisAsync()
更新后的参数名称:
// OpenIddict 3.x:
IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(string address, CancellationToken cancellationToken);
IAsyncEnumerable<TApplication> FindByRedirectUriAsync(string address, CancellationToken cancellationToken);
ValueTask SetPostLogoutRedirectUrisAsync(TApplication application, ImmutableArray<string> addresses, CancellationToken cancellationToken);
ValueTask SetRedirectUrisAsync(TApplication application, ImmutableArray<string> addresses, CancellationToken cancellationToken);
// OpenIddict 4.x:
IAsyncEnumerable<TApplication> FindByPostLogoutRedirectUriAsync(string uri, CancellationToken cancellationToken);
IAsyncEnumerable<TApplication> FindByRedirectUriAsync(string uri, CancellationToken cancellationToken);
ValueTask SetPostLogoutRedirectUrisAsync(TApplication application, ImmutableArray<string> uris, CancellationToken cancellationToken);
ValueTask SetRedirectUrisAsync(TApplication application, ImmutableArray<string> uris, CancellationToken cancellationToken);
考虑迁移到新的 OpenIddict 客户端(可选)
OpenIddict 4.0 引入了一个新的客户端堆栈,它原生兼容所有受支持的 ASP.NET Core 版本(.NET Framework 上的 2.1、3.1、6.0 和 7.0)以及Microsoft.Owin
4.2(这意味着它也可以在 ASP.NET 4.6.1 及以上版本上使用)。
欲了解更多详情,请阅读 OpenIddict 4.0 正式可用 。