#aspnet_mvc #dependency_injection #aspnet_identity_2 #owin
В базовом шаблоне при создании asp.net mvc проекта в качестве системы авторизации (по умолчанию) используется asp.net identity. public class ApplicationUser : IdentityUser { public async TaskGenerateUserIdentityAsync( UserManager manager) {} } public class ApplicationUserManager : UserManager { public ApplicationUserManager(IUserStore store) : base(store) {} public static ApplicationUserManager Create( IdentityFactoryOptions options, IOwinContext context) {} } public class ApplicationSignInManager : SignInManager { public ApplicationSignInManager( ApplicationUserManager userManager, IAuthenticationManager authenticationManager) : base(userManager, authenticationManager) { } public override Task CreateUserIdentityAsync(ApplicationUser user) {} public static ApplicationSignInManager Create( IdentityFactoryOptions options, IOwinContext context) {} } public class ApplicationDbContext : IdentityDbContext { public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) {} static ApplicationDbContext() {} public static ApplicationDbContext Create() {} } Указанные выше классы используются при настройки авторизации в приложении public partial class Startup { public void ConfigureAuth(IAppBuilder app) { // Configure the db context, user manager and role manager to use // a single instance per request app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext (ApplicationUserManager.Create); app.CreatePerOwinContext (ApplicationRoleManager.Create); app.CreatePerOwinContext (ApplicationSignInManager.Create); } } Как в приведенном коде избавиться от сильной зависимости - app.CreatePerOwinContext()?
Ответы
Ответ 1
Воспользуемся IoC контейнером Autofac для внедрения зависимостей. При помощи менеджера пакетов Nuget установим необходимые пакеты: Autofac Autofac ASP.NET MVC 5 Integration Autofac OWIN Integration Внесем следующие изменения в класс Startup: private void ConfigureContainer(IAppBuilder app) { var builder = new ContainerBuilder(); // STANDARD MVC SETUP: // Register your MVC controllers. builder.RegisterControllers(typeof(MvcApplication).Assembly); // Run other optional steps, like registering model binders, // web abstractions, etc., then set the dependency resolver // to be Autofac. builder.RegisterType().As ().InstancePerRequest(); builder.RegisterType () .As >().InstancePerRequest(); builder.RegisterType >() .As >().InstancePerRequest(); builder.Register ((c, p) => c.Resolve () .Authentication).InstancePerRequest(); var dataProtectionProvider = app.GetDataProtectionProvider(); builder.Register >((c, p) => BuildUserManager(c, p, dataProtectionProvider)); var container = builder.Build(); DependencyResolver.SetResolver(new AutofacDependencyResolver(container)); // OWIN MVC SETUP: // Register the Autofac middleware FIRST, then the Autofac MVC middleware. app.UseAutofacMiddleware(container); app.UseAutofacMvc(); } private UserManager BuildUserManager( IComponentContext context, IEnumerable parameters, IDataProtectionProvider dataProtectionProvider) { var manager = new ApplicationUserManager(context.Resolve >()); // Configure validation logic for usernames manager.UserValidator = new UserValidator (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 it in here. manager.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider { MessageFormat = "Your security code is {0}" }); manager.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider { Subject = "Security Code", BodyFormat = "Your security code is {0}" }); //manager.EmailService = new EmailService(); //manager.SmsService = new SmsService(); if (dataProtectionProvider != null) { manager.UserTokenProvider = new DataProtectorTokenProvider ( dataProtectionProvider.Create("ASP.NET Identity")); } return manager; } } Добавим вызов метода ConfigureContainer(IAppBuilder app) в метод Configuration(IAppBuilder app) public partial class Startup { public void Configuration(IAppBuilder app) { ConfigureAuth(app); ConfigureContainer(app); } } После выше приведенных действий можно удалить методы app.CreatePerOwinContext() из метода ConfigureAuth() так же необходимо модифицировать AccountControlle, ManageController: Убрать конструктор без параметров. Удалить следующие свойства: UserManager, SignInManager, AuthenticationManager Вот так может выглядеть AccountController после внесения необходимых изменений: public class AccountController : Controller { private readonly IAuthenticationManager _authenticationManager; private readonly SignInManager _signInManager; private readonly UserManager _userManager; public AccountController( UserManager userManager, SignInManager signInManager, IAuthenticationManager authenticationManager) { _authenticationManager = authenticationManager; _userManager = userManager; _signInManager = signInManager; } //Прочие необходимые методы } Использованные источники информации: Autofac’s documentation Habrahabr Ответ 2
Строка app.CreatePerOwinContext(ApplicationUserManager.Create); нужна фреймворку для того чтобы можно было получть объект ApplicationUserManager в SecurityStampValidator. Не обязательно оставлять код для ApplicationUserManager.Create но нужно научить фреймворк как получать инстанс ApplicationUserManager. Если используется DI контейнер, то можно будет заменать на app.CreatePerOwinContext(() => DependencyResolver.Current.GetService ());
Комментариев нет:
Отправить комментарий