尝试激活 Identity.IdentityUserManager 时无法解析类型 Identity.IdentityUserStore 的服务
Unable to resolve service for type Identity.IdentityUserStore while attempting to activate Identity.IdentityUserManager
我正在尝试在一个项目中使用 ASP.NET Core Identity 3.0,该项目的现有数据库未使用 Identity。因此我需要做一些定制,因为我想做一些更复杂的操作。
这是使用 .NET Core 3.1 完成的
但是当我 运行 现在的解决方案时,我得到了这两个例外:
InvalidOperationException:验证服务描述符时出错 'ServiceType: Microsoft.AspNetCore.Identity.ISecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SecurityStampValidator`1[ForumProject.Data.Identity.IdentityForumUser]':尝试激活 'ForumProject.Data.Identity.IdentityUserManager'. 时无法解析类型 'ForumProject.Data.Identity.IdentityUserStore' 的服务
InvalidOperationException:尝试激活 'ForumProject.Data.Identity.IdentityUserManager'.
时无法解析类型 'ForumProject.Data.Identity.IdentityUserStore' 的服务
我不知道我做错了什么,在我添加 UserStore 之前它一直在工作,所以我一定是创建错误,但到目前为止我找不到问题所在。
我在 startup.cs 的 ConfigureServices 中设置了这个:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IPasswordHasher<IdentityForumUser>, IdentityPasswordHasher>();
services.AddDbContext<DatabaseContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ForumDatabase")));
services.AddDbContext<IdentityDatabaseContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ForumDatabase")));
//services.AddIdentity<AppUser, IdentityRole>().AddEntityFrameworkStores<AppIdentityDbContext>().AddDefaultTokenProviders();
services.AddIdentity<IdentityForumUser, IdentityForumRole>(options =>
{
options.SignIn.RequireConfirmedAccount = false;
options.Password.RequiredLength = 2;
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 0;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
})
//.AddRoles<IdentityForumRole>()
.AddUserStore<IdentityUserStore>()
.AddUserManager<IdentityUserManager>()
//.AddSignInManager<IdentitySignInManager>()
.AddEntityFrameworkStores<IdentityDatabaseContext>();
services.AddMvc();
services.AddControllersWithViews();
services.AddRazorPages();
}
这是 IdentityForumUser、IdentityForumRole、IdentityDatabaseContext:
public class IdentityForumUser : IdentityUser<int>
{
[Column("Username")]
public override string UserName { get; set; }
[Column("Password")]
public override string PasswordHash { get; set; }
public int ThemeId { get; set; } = 1; /// TODO: Make it set to the picked default one
public int ChatStatus { get; set; } = 0;
public DateTime RegistrationDate { get; set; } = DateTime.UtcNow;
public bool DynamicMode { get; set; } = false;
public DateTime LastActivity { get; set; } = DateTime.UtcNow;
}
public class IdentityForumRole : IdentityRole<int>
{
}
public class IdentityDatabaseContext : IdentityDbContext<IdentityForumUser, IdentityForumRole, int>
{
public IdentityDatabaseContext(DbContextOptions<IdentityDatabaseContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<IdentityForumUser>()
.Ignore(c => c.LockoutEnd)
.Ignore(c => c.TwoFactorEnabled)
.Ignore(c => c.PhoneNumberConfirmed)
.Ignore(c => c.PhoneNumber)
.Ignore(c => c.ConcurrencyStamp)
.Ignore(c => c.EmailConfirmed)
.Ignore(c => c.NormalizedEmail)
//.Ignore(c => c.NormalizedUserName)
.Ignore(c => c.LockoutEnabled)
.Ignore(c => c.AccessFailedCount)
.ToTable("Users");
builder.Entity<IdentityForumRole>()
.Ignore(c => c.ConcurrencyStamp)
.ToTable("Roles");
}
}
这里是 IdentityUserStore,IdentityUserManager:
public class IdentityUserStore : UserStore<IdentityForumUser, IdentityForumRole, IdentityDatabaseContext, int>
{
public IdentityUserStore(IdentityDatabaseContext context, IdentityErrorDescriber describer = null) : base(context, describer)
{
}
}
public class IdentityUserManager : UserManager<IdentityForumUser>
{
public IdentityUserManager(IdentityUserStore store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityForumUser> passwordHasher, IEnumerable<IUserValidator<IdentityForumUser>> userValidators,
IEnumerable<IPasswordValidator<IdentityForumUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<IdentityUserManager> logger)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
}
public override bool SupportsUserClaim
{
get
{
ThrowIfDisposed();
return false;
}
}
}
这是 IdentityPasswordHasher,但只是其中的一部分,我将注释掉逻辑本身,我不确定这是否相关:
public class IdentityPasswordHasher : PasswordHasher<IdentityForumUser>
{
private readonly PasswordHasherCompatibilityMode _compatibilityMode;
public IdentityPasswordHasher(IOptions<PasswordHasherOptions> optionsAccessor = null)
: base(optionsAccessor)
{
var options = optionsAccessor?.Value ?? new PasswordHasherOptions();
_compatibilityMode = options.CompatibilityMode;
}
public override string HashPassword(IdentityForumUser user, string password)
{
// custom hashing code
}
public override PasswordVerificationResult VerifyHashedPassword(IdentityForumUser user, string hashedPassword, string providedPassword)
{
// custom verification code
}
}
在 IdentityUserManager
的构造函数中,我将其更改为使用 IUserStore<IdentityForumUser> store
,而不是 IdentityUserStore store
(我的自定义 class)。
这使它工作并且仍然使用我的自定义商店 class。
但是,我不高兴我不能明确,因为它使代码更容易理解。
如果有明确的方法,也请回答。
我正在尝试在一个项目中使用 ASP.NET Core Identity 3.0,该项目的现有数据库未使用 Identity。因此我需要做一些定制,因为我想做一些更复杂的操作。
这是使用 .NET Core 3.1 完成的
但是当我 运行 现在的解决方案时,我得到了这两个例外:
InvalidOperationException:验证服务描述符时出错 'ServiceType: Microsoft.AspNetCore.Identity.ISecurityStampValidator Lifetime: Scoped ImplementationType: Microsoft.AspNetCore.Identity.SecurityStampValidator`1[ForumProject.Data.Identity.IdentityForumUser]':尝试激活 'ForumProject.Data.Identity.IdentityUserManager'. 时无法解析类型 'ForumProject.Data.Identity.IdentityUserStore' 的服务
InvalidOperationException:尝试激活 'ForumProject.Data.Identity.IdentityUserManager'.
时无法解析类型 'ForumProject.Data.Identity.IdentityUserStore' 的服务我不知道我做错了什么,在我添加 UserStore 之前它一直在工作,所以我一定是创建错误,但到目前为止我找不到问题所在。
我在 startup.cs 的 ConfigureServices 中设置了这个:
public void ConfigureServices(IServiceCollection services)
{
services.AddScoped<IPasswordHasher<IdentityForumUser>, IdentityPasswordHasher>();
services.AddDbContext<DatabaseContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ForumDatabase")));
services.AddDbContext<IdentityDatabaseContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("ForumDatabase")));
//services.AddIdentity<AppUser, IdentityRole>().AddEntityFrameworkStores<AppIdentityDbContext>().AddDefaultTokenProviders();
services.AddIdentity<IdentityForumUser, IdentityForumRole>(options =>
{
options.SignIn.RequireConfirmedAccount = false;
options.Password.RequiredLength = 2;
options.Password.RequireDigit = false;
options.Password.RequireLowercase = false;
options.Password.RequiredUniqueChars = 0;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireUppercase = false;
})
//.AddRoles<IdentityForumRole>()
.AddUserStore<IdentityUserStore>()
.AddUserManager<IdentityUserManager>()
//.AddSignInManager<IdentitySignInManager>()
.AddEntityFrameworkStores<IdentityDatabaseContext>();
services.AddMvc();
services.AddControllersWithViews();
services.AddRazorPages();
}
这是 IdentityForumUser、IdentityForumRole、IdentityDatabaseContext:
public class IdentityForumUser : IdentityUser<int>
{
[Column("Username")]
public override string UserName { get; set; }
[Column("Password")]
public override string PasswordHash { get; set; }
public int ThemeId { get; set; } = 1; /// TODO: Make it set to the picked default one
public int ChatStatus { get; set; } = 0;
public DateTime RegistrationDate { get; set; } = DateTime.UtcNow;
public bool DynamicMode { get; set; } = false;
public DateTime LastActivity { get; set; } = DateTime.UtcNow;
}
public class IdentityForumRole : IdentityRole<int>
{
}
public class IdentityDatabaseContext : IdentityDbContext<IdentityForumUser, IdentityForumRole, int>
{
public IdentityDatabaseContext(DbContextOptions<IdentityDatabaseContext> options)
: base(options)
{
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
builder.Entity<IdentityForumUser>()
.Ignore(c => c.LockoutEnd)
.Ignore(c => c.TwoFactorEnabled)
.Ignore(c => c.PhoneNumberConfirmed)
.Ignore(c => c.PhoneNumber)
.Ignore(c => c.ConcurrencyStamp)
.Ignore(c => c.EmailConfirmed)
.Ignore(c => c.NormalizedEmail)
//.Ignore(c => c.NormalizedUserName)
.Ignore(c => c.LockoutEnabled)
.Ignore(c => c.AccessFailedCount)
.ToTable("Users");
builder.Entity<IdentityForumRole>()
.Ignore(c => c.ConcurrencyStamp)
.ToTable("Roles");
}
}
这里是 IdentityUserStore,IdentityUserManager:
public class IdentityUserStore : UserStore<IdentityForumUser, IdentityForumRole, IdentityDatabaseContext, int>
{
public IdentityUserStore(IdentityDatabaseContext context, IdentityErrorDescriber describer = null) : base(context, describer)
{
}
}
public class IdentityUserManager : UserManager<IdentityForumUser>
{
public IdentityUserManager(IdentityUserStore store, IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<IdentityForumUser> passwordHasher, IEnumerable<IUserValidator<IdentityForumUser>> userValidators,
IEnumerable<IPasswordValidator<IdentityForumUser>> passwordValidators, ILookupNormalizer keyNormalizer,
IdentityErrorDescriber errors, IServiceProvider services, ILogger<IdentityUserManager> logger)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
}
public override bool SupportsUserClaim
{
get
{
ThrowIfDisposed();
return false;
}
}
}
这是 IdentityPasswordHasher,但只是其中的一部分,我将注释掉逻辑本身,我不确定这是否相关:
public class IdentityPasswordHasher : PasswordHasher<IdentityForumUser>
{
private readonly PasswordHasherCompatibilityMode _compatibilityMode;
public IdentityPasswordHasher(IOptions<PasswordHasherOptions> optionsAccessor = null)
: base(optionsAccessor)
{
var options = optionsAccessor?.Value ?? new PasswordHasherOptions();
_compatibilityMode = options.CompatibilityMode;
}
public override string HashPassword(IdentityForumUser user, string password)
{
// custom hashing code
}
public override PasswordVerificationResult VerifyHashedPassword(IdentityForumUser user, string hashedPassword, string providedPassword)
{
// custom verification code
}
}
在 IdentityUserManager
的构造函数中,我将其更改为使用 IUserStore<IdentityForumUser> store
,而不是 IdentityUserStore store
(我的自定义 class)。
这使它工作并且仍然使用我的自定义商店 class。 但是,我不高兴我不能明确,因为它使代码更容易理解。 如果有明确的方法,也请回答。