我尝试隔离ASP.NET Core Identity版本1.1.2,架构DDD并创建一个CrossCutting层来为aspnet核心身份创建一个classlib,我使用SimpleInjector 4.0.8为我的IoC,所以我创建了一个类ApplicationUserManager和ApplicationSignInManager,但我不能在simlpleinjector容器中注册这个类
ApplicationUserManager
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store,
IOptions<IdentityOptions> optionsAccessor,
IPasswordHasher<ApplicationUser> passwordHasher,
IEnumerable<IUserValidator<ApplicationUser>> userValidators,
IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators,
ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors,
IServiceProvider services,
ILogger<UserManager<ApplicationUser>> logger)
: base(store, optionsAccessor, passwordHasher, userValidators, passwordValidators, keyNormalizer, errors, services, logger)
{
// My configurations stuffs were...
}
}
和类 ApplicationSignInManager
public class ApplicationSignInManager : SignInManager<ApplicationUser>
{
public ApplicationSignInManager(UserManager<ApplicationUser> userManager,
IHttpContextAccessor contextAccessor,
IUserClaimsPrincipalFactory<ApplicationUser> claimsFactory,
IOptions<IdentityOptions> optionsAccessor,
ILogger<SignInManager<ApplicationUser>> logger)
: base(userManager, contextAccessor, claimsFactory, optionsAccessor, logger)
{ }
// TODO: bug com tipo de retorno IdentityResult para ClaimsPrincipal
//public override Task<ClaimsPrincipal> CreateUserPrincipalAsync(ApplicationUser user)
//{
// return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
//}
}
我尝试在 BootStrapper.cs 中注册此类
public static void RegisterServices(Container container)
{
// Infra.Data App Context
// IdentityAppDbContext
container.RegisterSingleton(() =>
{
var options = new DbContextOptions<IdentityAppDbContext>();
return new IdentityAppDbContext(options);
});
// NetCore Identity
container.RegisterSingleton<ApplicationUserManager>();
container.RegisterSingleton<ApplicationSignInManager>();
container.RegisterSingleton<IUserStore<ApplicationUser>>(() =>
{
var options = new DbContextOptions<IdentityAppDbContext>();
return new UserStore<ApplicationUser>(new IdentityAppDbContext(options));
});
container.Register(() => (IOptions<IdentityOptions>)new IdentityOptions());
container.RegisterSingleton<IPasswordHasher<ApplicationUser>>(() => new PasswordHasher<ApplicationUser>());
}
但是当我运行aaplication返回错误说我需要注册表IOptions,IPasswordHasher和其他参与者类中的参数,问题是,如何才能注册这个类?
答案 0 :(得分:1)
我有类似的要求:我的应用程序需要与身份进行交互(它基本上是关于人力资源,可能有自己的用户帐户),经过长时间的努力与各种问题在框架容器,我试图配置简单的注入器来提供所有身份服务。称之为疯狂,但这是它的工作原理(SimpleInjector 4.0和ASP.Net Identity Core 2.0.1):
这是“ConfigureServices”部分:
POSIXct
这需要在“配置”期间完成,否则密码重置和其他两个因素令牌内容将不起作用(运行时错误,尽管容器已经过验证)
// identity options are provided from outside, allowing configuration of the framework
container.RegisterSingleton<IOptions<IdentityOptions>>(new OptionsWrapper<IdentityOptions>(identityOptions));
// we rely on BCrypt instead of the default PBKDF2 hashing algorithm
container.Register<IPasswordHasher<MepUser>>(()=>new BCryptPasswordHasher(bcryptOptions));
// forwarding the framework logger to our own logging framework
container.Register<Microsoft.Extensions.Logging.ILoggerFactory, FrameworkToBackendFxLoggerFactory>();
container.Register(typeof(Microsoft.Extensions.Logging.ILogger<>), typeof(Microsoft.Extensions.Logging.Logger<>));
// identity store = a specific Entity Framework Core DbContext, getting mapped into a specific db scheme
container.RegisterSingleton(identityDbContextOptions);
container.Register<MepIdentityDbContext>();
// UserStore<T> und RoleStore<T> both require a DbContext (no IdentityDbContext, neither a generic TDbContext)
// via constructor, but the container only knows about MepIdentityDbContext so we have to wire it manually
container.Register<IUserStore<MepUser>>(() => new UserStore<MepUser>(
container.GetInstance<MepIdentityDbContext>(),
container.GetInstance<IdentityErrorDescriber>()));
container.Register<IRoleStore<IdentityRole>>(() => new RoleStore<IdentityRole>(
container.GetInstance<MepIdentityDbContext>(),
container.GetInstance<IdentityErrorDescriber>()));
// framework internal services
container.Register<IdentityErrorDescriber>();
container.Register<ILookupNormalizer, UpperInvariantLookupNormalizer>();
container.Register<IPasswordValidator<MepUser>, PasswordValidator<MepUser>>();
container.Register<IUserValidator<MepUser>, UserValidator<MepUser>>();
container.Register<IUserClaimsPrincipalFactory<MepUser>, UserClaimsPrincipalFactory<MepUser>>();
container.Register<IRoleValidator<IdentityRole>, RoleValidator<IdentityRole>>();
// ASP.Net Core Identity violates a design decision of SimpleInjector: The API clearly differentiates the registration of collections
// https://simpleinjector.readthedocs.io/en/latest/decisions.html#the-api-clearly-differentiates-the-registration-of-collections
// By registering IEnumerables of those violating services with a simple wrapping single item array, Identity is happy
container.Register<IEnumerable<IUserValidator<MepUser>>>(() => new[] { container.GetInstance<IUserValidator<MepUser>>() });
container.Register<IEnumerable<IRoleValidator<IdentityRole>>>(() => new[] { container.GetInstance<IRoleValidator<IdentityRole>>() });
container.Register<IEnumerable<IPasswordValidator<MepUser>>>(() => new[] { container.GetInstance<IPasswordValidator<MepUser>>() });
// Role and UserManager reflect the API surface of the whole ASP.Net Core Identity framework
container.Register<RoleManager<IdentityRole>>();
// UserManagerShim is omitting (=nulling) the IServiceProvider parameter of UserManager<T>
container.Register<UserManager<MepUser>, UserManagerShim>();
虽然名称空间定义中出现// if you eagerly instantiate a provider instance that is considered being a singleton and
// put it into the respective field in the TokenProviderDescriptor and list it in the option's
// provider map, ASP.Net Core Identity will use this one instead of asking the IServiceProvider
// instance injected into UserManager<T> (that we do not do, because it is bad design. Instead,
// we just stuff null in there)
identityOptions.Tokens.ProviderMap[TokenOptions.DefaultProvider] =
new TokenProviderDescriptor(typeof(DataProtectorTokenProvider<MepUser>))
{
ProviderInstance = new DataProtectorTokenProvider<MepUser>(
dataProtectionProvider,
new OptionsWrapper<DataProtectionTokenProviderOptions>(new DataProtectionTokenProviderOptions()))
};
identityOptions.Tokens.ProviderMap[TokenOptions.DefaultEmailProvider] =
new TokenProviderDescriptor(typeof(EmailTokenProvider<MepUser>)) {
ProviderInstance = new EmailTokenProvider<MepUser>()
};
,但实际上并没有任何内容依赖于ASP.Net Core托管。对“外部世界”的唯一依赖是选项(POCO)和AspNetCore
的实现,它将在ASP.Net场景中使用IDataProtectionProvider
,但也可以使用{{1}来满足在测试中。
警告:KeyRing
未被注入。这个课程完全混乱,取决于整个世界,所以我重写了它基本符合我的要求。您还失去了许多关于令牌提供程序的配置灵活性。但是,在我的情况下,这是你在设计时决定的一次,所以我很好。