Asp.Net 核心身份 - UserManager.Users.Any() returns 始终为 false
Asp.Net core identity - UserManager.Users.Any() returns always false
这是我第一次尝试创建 IDP。我选择使用 Asp.Net Core Identity (3.1.4) 和 IdentityServer4 (3.1.3)。一开始我只是使用 IdentityUser
时一切正常,但昨天我想为我的用户添加一些属性,所以我决定添加一个 class ApplicationUser
来保存这些属性, ApplicationUser
当然来自 IdentityUser
.
因此,我将所有使用 IdentityUser
的实例替换为 ApplicationUser
,并认为到此结束。但是你瞧,今天当我尝试编译以测试我的工作时,我发现在创建后将用户添加到数据库的播种方法找不到任何用户,因此总是试图一遍又一遍地添加相同的用户。
我发现这段代码没有正常工作。从现在开始,它总是给我 false
,尽管已经在数据库中创建了 3 个用户。尽管我必须说用户是在我将 ApplicationUser
添加到项目之前创建的。
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
if (!userManager.Users.Any())
{
string password = string.Empty;
foreach (var testUser in Users.Get())
{
var identityUser = new ApplicationUser(testUser.Username)
{
Id = testUser.SubjectId,
};
password = testUser.Password;
var passwordValidators = userManager.PasswordValidators;
List<string> passwordErrors = new List<string>();
foreach (var validator in passwordValidators)
{
IdentityResult result = await validator.ValidateAsync(userManager, null, password);
if (!result.Succeeded)
{
foreach (var error in result.Errors)
{
passwordErrors.Add(error.Description);
}
}
}
if (string.IsNullOrEmpty(password) || passwordErrors.Count > 0)
{
password = "Password123!";
}
userManager.CreateAsync(identityUser, password).Wait();
userManager.AddClaimsAsync(identityUser, testUser.Claims.ToList()).Wait();
}
}
如果您想查看我在 ConfigureServices
中的 startup.cs
中的 IdentityServer 和网络核心身份,这里是:
string connectionStringISD = Configuration.GetConnectionString("IdentityServerData");
string connectionStringUDB = Configuration.GetConnectionString("UsersDB");
string migrationsAssembly = typeof(Startup)
.GetTypeInfo().Assembly.GetName().Name;
services.AddDbContext<IDPContext>(o => o.UseSqlServer(connectionStringUDB, so => so.MigrationsAssembly(migrationsAssembly)));
services.AddIdentity<ApplicationUser, IdentityRole>()//options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<IDPContext>()
.AddDefaultTokenProviders();
var IS4Builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.UserInteraction.LoginUrl = "/Account/Login"; //do i need this?
options.UserInteraction.LogoutUrl = "/Account/Logout"; //do I need this?
options.Authentication = new AuthenticationOptions()
{
CookieSlidingExpiration = true
};
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options => {
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionStringISD, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly));
options.EnableTokenCleanup = true;
})
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionStringISD, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
.AddAspNetIdentity<ApplicationUser>();
if (Environment.IsDevelopment())
{
IS4Builder.AddDeveloperSigningCredential();
}
else
{
IS4Builder.AddSigningCredential(LoadCertificateFromStore(Configuration.GetValue<string>("SigningCertificate")));
}
这也是我如何在 Configure
方法中调用播种方法
ConfigurationDbContextExtension.InitializeDbDataAsync(app).Wait();
有什么想法吗?如果可能,我想避免必须销毁和重新创建数据库。
您提到您使用 ApplicationUser class 添加了更多属性。
如果您使用 Code First 迁移,则应使用 ef add 迁移命令。和更新数据库方案。
我只是假设你忘了做迁移:)
换句话说,确保您的 ApplicationUser 在字段方面与 AspNetUsers table 同步。
所以,经过更多的挖掘,我发现因为我已经在最初使用 IdentityUser 时创建了我的 AspNetUsers table,所以我需要删除现有的本地数据库以避免可能的 table 碰撞。不幸的是,添加并成功应用迁移并不是答案
这是我第一次尝试创建 IDP。我选择使用 Asp.Net Core Identity (3.1.4) 和 IdentityServer4 (3.1.3)。一开始我只是使用 IdentityUser
时一切正常,但昨天我想为我的用户添加一些属性,所以我决定添加一个 class ApplicationUser
来保存这些属性, ApplicationUser
当然来自 IdentityUser
.
因此,我将所有使用 IdentityUser
的实例替换为 ApplicationUser
,并认为到此结束。但是你瞧,今天当我尝试编译以测试我的工作时,我发现在创建后将用户添加到数据库的播种方法找不到任何用户,因此总是试图一遍又一遍地添加相同的用户。
我发现这段代码没有正常工作。从现在开始,它总是给我 false
,尽管已经在数据库中创建了 3 个用户。尽管我必须说用户是在我将 ApplicationUser
添加到项目之前创建的。
var userManager = scope.ServiceProvider.GetRequiredService<UserManager<ApplicationUser>>();
if (!userManager.Users.Any())
{
string password = string.Empty;
foreach (var testUser in Users.Get())
{
var identityUser = new ApplicationUser(testUser.Username)
{
Id = testUser.SubjectId,
};
password = testUser.Password;
var passwordValidators = userManager.PasswordValidators;
List<string> passwordErrors = new List<string>();
foreach (var validator in passwordValidators)
{
IdentityResult result = await validator.ValidateAsync(userManager, null, password);
if (!result.Succeeded)
{
foreach (var error in result.Errors)
{
passwordErrors.Add(error.Description);
}
}
}
if (string.IsNullOrEmpty(password) || passwordErrors.Count > 0)
{
password = "Password123!";
}
userManager.CreateAsync(identityUser, password).Wait();
userManager.AddClaimsAsync(identityUser, testUser.Claims.ToList()).Wait();
}
}
如果您想查看我在 ConfigureServices
中的 startup.cs
中的 IdentityServer 和网络核心身份,这里是:
string connectionStringISD = Configuration.GetConnectionString("IdentityServerData");
string connectionStringUDB = Configuration.GetConnectionString("UsersDB");
string migrationsAssembly = typeof(Startup)
.GetTypeInfo().Assembly.GetName().Name;
services.AddDbContext<IDPContext>(o => o.UseSqlServer(connectionStringUDB, so => so.MigrationsAssembly(migrationsAssembly)));
services.AddIdentity<ApplicationUser, IdentityRole>()//options => options.SignIn.RequireConfirmedAccount = true)
.AddEntityFrameworkStores<IDPContext>()
.AddDefaultTokenProviders();
var IS4Builder = services.AddIdentityServer(options =>
{
options.Events.RaiseErrorEvents = true;
options.Events.RaiseInformationEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseSuccessEvents = true;
options.UserInteraction.LoginUrl = "/Account/Login"; //do i need this?
options.UserInteraction.LogoutUrl = "/Account/Logout"; //do I need this?
options.Authentication = new AuthenticationOptions()
{
CookieSlidingExpiration = true
};
})
// this adds the operational data from DB (codes, tokens, consents)
.AddOperationalStore(options => {
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionStringISD, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly));
options.EnableTokenCleanup = true;
})
// this adds the config data from DB (clients, resources)
.AddConfigurationStore(options =>
options.ConfigureDbContext = builder =>
builder.UseSqlServer(connectionStringISD, sqlOptions => sqlOptions.MigrationsAssembly(migrationsAssembly)))
.AddAspNetIdentity<ApplicationUser>();
if (Environment.IsDevelopment())
{
IS4Builder.AddDeveloperSigningCredential();
}
else
{
IS4Builder.AddSigningCredential(LoadCertificateFromStore(Configuration.GetValue<string>("SigningCertificate")));
}
这也是我如何在 Configure
方法中调用播种方法
ConfigurationDbContextExtension.InitializeDbDataAsync(app).Wait();
有什么想法吗?如果可能,我想避免必须销毁和重新创建数据库。
您提到您使用 ApplicationUser class 添加了更多属性。
如果您使用 Code First 迁移,则应使用 ef add 迁移命令。和更新数据库方案。 我只是假设你忘了做迁移:)
换句话说,确保您的 ApplicationUser 在字段方面与 AspNetUsers table 同步。
所以,经过更多的挖掘,我发现因为我已经在最初使用 IdentityUser 时创建了我的 AspNetUsers table,所以我需要删除现有的本地数据库以避免可能的 table 碰撞。不幸的是,添加并成功应用迁移并不是答案