use*_*196 5 c# asp.net-identity asp.net-core identityserver4
我的应用程序和 API 使用 IdentityServer 4 进行保护。
我有一个用于用户管理的集中 API(注册新用户、更新、删除和重置密码)。这个 api 生成的令牌将被 identityserver 用来重置用户的密码。
问题是我总是收到无效令牌错误。我知道这与 url 编码无关,因为忘记的密码由身份服务器处理,并且身份服务器生成的令牌工作正常。问题是当令牌由不同的 api 生成时(即使在一台机器上)。
我考虑创建一个通用的数据保护提供程序,但我不清楚这是如何完成的。基本上,我怎样才能重置由另一个接受的一个 api 创建的密码令牌?
我正在使用 Asp Identity 的用户管理器来生成重置密码令牌:
var token = await _userManager.GeneratePasswordResetTokenAsync(appUser);
Run Code Online (Sandbox Code Playgroud)
这是我的 IdentityServer 被设置为使用 Asp Identity 的方式:
services
.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Lockout.AllowedForNewUsers = true;
options.Lockout.DefaultLockoutTimeSpan = new System.TimeSpan(12, 0, 0);
options.Lockout.MaxFailedAccessAttempts = int.Parse(Configuration["MaxFailedAttempts"]);
})
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
...
var builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.Authentication.CookieSlidingExpiration = true;
})
.AddAspNetIdentity<ApplicationUser>()
.AddConfigurationStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
options.DefaultSchema = Globals.SCHEMA_IDS;
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options =>
{
options.ConfigureDbContext = b =>
b.UseSqlServer(connectionString,
sql => sql.MigrationsAssembly(migrationsAssembly));
options.DefaultSchema = Globals.SCHEMA_IDS;
// this enables automatic token cleanup. this is optional.
options.EnableTokenCleanup = true;
options.TokenCleanupInterval = 30;
})
.AddProfileService<CustomProfileService>()
.AddSigninCredentialFromConfig(Configuration.GetSection("SigninKeyCredentials"), Logger);
Run Code Online (Sandbox Code Playgroud)
这就是我的 UserManagement Api 设置为使用 Asp Identity 的方式:
services.AddTransient<IUserStore<ApplicationUser>, UserStore<ApplicationUser, IdentityRole, ApplicationDbContext>>();
services.AddTransient<IRoleStore<IdentityRole>, RoleStore<IdentityRole, ApplicationDbContext>>();
services.AddTransient<IPasswordHasher<ApplicationUser>, PasswordHasher<ApplicationUser>>();
services.AddTransient<ILookupNormalizer, UpperInvariantLookupNormalizer>();
services.AddTransient<IdentityErrorDescriber>();
var identityBuilder = new IdentityBuilder(typeof(ApplicationUser), typeof(IdentityRole), services);
identityBuilder.AddTokenProvider("Default", typeof(DataProtectorTokenProvider<ApplicationUser>));
services.AddTransient<UserManager<ApplicationUser>>();
Run Code Online (Sandbox Code Playgroud)
必须继续讨论其他问题,现在才回到这个问题。我最终通过确保所有 API 和 IdentityServer 实例都配置为使用 ASP.NET Core 数据保护来解决这个问题。我使用 Redis 作为我的分布式缓存系统,因此只需配置我的每个 api 和身份服务器,并且现在在生成令牌时所有内容都使用相同的密钥。以下是我在每个startup.cs中使用的内容:
public void ConfigureServices(IServiceCollection services)
{
...
services.AddSession();
services.Configure<RedisConfiguration>(Configuration.GetSection("redis"));
services.AddDistributedRedisCache(options =>
{
options.Configuration = Configuration.GetValue<string>("redis:host");
});
var redis = ConnectionMultiplexer.Connect(Configuration.GetValue<string>("redis:host"));
services.AddDataProtection()
.PersistKeysToRedis(redis, "DataProtection-Keys")
.SetApplicationName(<application name>);
services.AddTransient<ICacheService, CacheService>();
...
}
Run Code Online (Sandbox Code Playgroud)
然后不要忘记使用会话(在 API 中):
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseAuthentication();
app.UseSession();
...
}
Run Code Online (Sandbox Code Playgroud)
使用会话(在 IdentityServer 中):
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
...
app.UseIdentityServer();
app.UseSession();
...
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7972 次 |
| 最近记录: |