Регистрация IAuthenticationManager с Unity
Я использую Unity for Dependencies Injection и используя Identity Provider для управления входом пользователя, регистрации, подтверждения по электронной почте и т.д.
Когда я пытаюсь зарегистрировать пользователя, у меня есть эта проблема:
Текущий тип, Microsoft.Owin.Security.IAuthenticationManager, является интерфейс и не может быть сконструирован. Вам не хватает типа отображение?
Я не знаю, как зарегистрировать этот интерфейс (IAuthenticationManager) в контейнере Unity.
Я попытался зарегистрировать интерфейс с этим кодом, но если я его положу, у меня есть другая проблема:
Не зарегистрирован IUserTokenProvider.
container.RegisterType<HttpContextBase>(
new InjectionFactory(_ => new HttpContextWrapper(HttpContext.Current)));
container.RegisterType<IOwinContext>(new InjectionFactory(c => c.Resolve<HttpContextBase>().GetOwinContext()));
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(c => c.Resolve<IOwinContext>().Authentication));
Я добавил код приложения (если я не использую Unity, все работает нормально):
AccountController
private IAuthenticationManager AuthenticationManager
{
get
{
return HttpContext.GetOwinContext().Authentication;
}
}
IdentityConfig.cs
public class ApplicationUserManager : UserManager<ApplicationUser>
{
public ApplicationUserManager(IUserStore<ApplicationUser> store)
: base(store)
{
}
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options,
IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Configure user lockout defaults
manager.UserLockoutEnabledByDefault = true;
manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
manager.MaxFailedAccessAttemptsBeforeLockout = 5;
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug in here.
manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is: {0}"
});
manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
{
Subject = "SecurityCode",
BodyFormat = "Your security code is {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider =
new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
}
// Configure the RoleManager used in the application. RoleManager is defined in the ASP.NET Identity core assembly
public class ApplicationRoleManager : RoleManager<IdentityRole>
{
public ApplicationRoleManager(IRoleStore<IdentityRole, string> roleStore)
: base(roleStore)
{
}
public static ApplicationRoleManager Create(IdentityFactoryOptions<ApplicationRoleManager> options, IOwinContext context)
{
return new ApplicationRoleManager(new RoleStore<IdentityRole>(context.Get<ApplicationDbContext>()));
}
}
public class EmailService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
// Plug in your email service here to send an email.
return Task.FromResult(0);
}
}
public class SmsService : IIdentityMessageService
{
public Task SendAsync(IdentityMessage message)
{
// Plug in your sms service here to send a text message.
return Task.FromResult(0);
}
}
// This is useful if you do not want to tear down the database each time you run the application.
// public class ApplicationDbInitializer : DropCreateDatabaseAlways<ApplicationDbContext>
// This example shows you how to create a new database if the Model changes
public class ApplicationDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>
{
protected override void Seed(ApplicationDbContext context)
{
InitializeIdentityForEF(context);
base.Seed(context);
}
//Create [email protected] with [email protected] in the Admin role
public static void InitializeIdentityForEF(ApplicationDbContext db)
{
var userManager = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();
var roleManager = HttpContext.Current.GetOwinContext().Get<ApplicationRoleManager>();
const string name = "[email protected]";
const string password = "[email protected]";
const string roleName = "Admin";
//Create Role Admin if it does not exist
var role = roleManager.FindByName(roleName);
if (role == null)
{
role = new IdentityRole(roleName);
var roleresult = roleManager.Create(role);
}
var user = userManager.FindByName(name);
if (user == null)
{
user = new ApplicationUser { UserName = name, Email = name };
var result = userManager.Create(user, password);
result = userManager.SetLockoutEnabled(user.Id, false);
}
// Add user admin to Role Admin if not already added
var rolesForUser = userManager.GetRoles(user.Id);
if (!rolesForUser.Contains(role.Name))
{
var result = userManager.AddToRole(user.Id, role.Name);
}
}
}
public class ApplicationSignInManager : SignInManager<ApplicationUser, string>
{
public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
:
base(userManager, authenticationManager)
{
}
public override Task<ClaimsIdentity> CreateUserIdentityAsync(ApplicationUser user)
{
return user.GenerateUserIdentityAsync((ApplicationUserManager)UserManager);
}
public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context)
{
return new ApplicationSignInManager(context.GetUserManager<ApplicationUserManager>(), context.Authentication);
}
}
Спасибо!!
Ответы
Ответ 1
Вот что я сделал, чтобы Unity хорошо играла с ASP.NET Identity 2.0:
Я добавил следующее в метод RegisterTypes
в классе UnityConfig
:
container.RegisterType<DbContext, ApplicationDbContext>(
new HierarchicalLifetimeManager());
container.RegisterType<UserManager<ApplicationUser>>(
new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(
new HierarchicalLifetimeManager());
container.RegisterType<AccountController>(
new InjectionConstructor());
Ответ 2
Попробуйте добавить строку ниже в классе UnityConfig
:
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(
o => System.Web.HttpContext.Current.GetOwinContext().Authentication
)
);
Ответ 3
Если вы действительно хотите использовать Unity для управления всеми вашими зависимостями, вы можете попытаться также зарегистрировать IAuthenticationManager в Unity
container.RegisterType<IAuthenticationManager>(
new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));
С некоторыми небольшими изменениями вы можете использовать Unity для разрешения всех необходимых зависимостей для Identity Asp.net.
Я нашел отличный пост на этом (также проверенный мной) здесь:
http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration/
Ответ 4
Это также будет работать как полная конфигурация, позволяющая использовать Unity с Identity 2.0:
container.RegisterType<MyDbContext>(new PerRequestLifetimeManager(), new InjectionConstructor());
// Identity
container.RegisterType<UserManager<User>>(new HierarchicalLifetimeManager());
container.RegisterType<SignInManager<User, string>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<User>, UserStore<User>>(new PerRequestLifetimeManager(), new InjectionFactory(x => new UserStore<User>(GetConfiguredContainer().Resolve<MyDbContext>())));
container.RegisterType<IAuthenticationManager>(new InjectionFactory(x => HttpContext.Current.GetOwinContext().Authentication));
С помощью этого параметра вам не нужно будет регистрировать типы AccountController или ManageController с Unity.
Ответ 5
Репутация не позволит мне комментировать, но для добавления отмеченного ответа user3849637s для MVC с Update 3 вам также потребуется добавить ManageController, поскольку некоторые функции используют это с обновленными лесами:
container.RegisterType<ManageController>(new InjectionConstructor());
Ответ 6
container.RegisterFactory<IAuthenticationManager>(o => System.Web.HttpContext.Current.GetOwinContext().Authentication);
Это ответит на вопрос, опубликованный ОП, и будет актуальным ответом для любого, кто найдет это через Google, как я. RegisterFactory - это новый способ сделать это в Unity.