Я пытаюсь использовать ASP. NET Core Identity 3.0 в проекте с существующей БД, которая не использовала Identity. Поэтому мне нужно выполнить некоторые настройки из-за этого и потому, что я хочу сделать более сложные операции.
Это делается с помощью. NET Core 3.1
Но когда я запускаю решение правильно теперь я получаю эти 2 исключения:
InvalidOperationException: Ошибка при проверке дескриптора службы 'ServiceType: Microsoft.AspNetCore.Identity.ISecurityStampValidator Срок действия: Ограниченная реализацияType: Microsoft.AspNetCore.Identity.SecurityStampaljectIDject .Data.Identity.IdentityForumUser] ': невозможно разрешить службу для типа' ForumProject.Data.Identity.IdentityUserStore 'при попытке активировать' ForumProject.Data.Identity.IdentityUserManager '.
InvalidOperationException: невозможно разрешить службу для типа «ForumProject.Data.Identity.IdentityUserStore» при попытке активировать «ForumProject.Data.Identity.IdentityUserManager».
Понятия не имею, что я делаю неправильно, это работало, пока я не добавил UserStore , поэтому я, должно быть, создаю это неправильно, но я не могу найти, в чем проблема.
У меня это настроено в ConfigureServices в startup.cs:
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, но только его части, я буду комментировать сама логика c, я не уверен, что это актуально:
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
}
}