注入 SignInManager 依賴項:不適用於 Unity,在使用 OWIN 時有效
我正在向 ASP.NET MVC 5 Web 應用程序添加 ASP.NET Identity 身份驗證功能。
我在整個項目中使用 Unity 進行依賴注入,所以我決定
AccountController在建構子中註入所需的依賴:public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser, string> signInManager) { _userManager = userManager; _signInManager = signInManager; }我的
Login方法實現如下(實際上,我從ASP.NET Web Application帶有身份驗證的項目模板中複製了該程式碼Individual User Accounts):// // POST: /Account/Login [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true); // Process result and return appropriate view... // However, there are no authentication cookies in the response! }問題是身份驗證無法正常工作 - 即使我輸入了正確的憑據並且
result是SignInStatus.Success,響應中也沒有發送身份驗證 cookie。但是,如果我使用基礎設施而不是 Unity 容器
OWIN來解析,則一切正常:ApplicationSignInManager// // POST: /Account/Login [HttpPost] [AllowAnonymous] [ValidateAntiForgeryToken] public async Task<ActionResult> Login(LoginViewModel model, string returnUrl) { var owinSignInManager = HttpContext.GetOwinContext().Get<ApplicationSignInManager>(); var result = await owinSignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true); // Process result and return appropriate view... // Authentication cookies are present in the response! }這就是在應用程序類
ApplicationSignInManager中註冊的方式:Startupapp.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);這是
ApplicationSignInManager聲明:public class ApplicationSignInManager : SignInManager<ApplicationUser, string> { public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) : base(userManager, authenticationManager) { } public static ApplicationSignInManager Create(IdentityFactoryOptions<ApplicationSignInManager> options, IOwinContext context) { var userManager = new ApplicationUserManager(new UserStore<ApplicationUser>(new DatabaseContext())); return new ApplicationSignInManager(userManager, context.Authentication); } }這是我的 Unity 配置的一部分:
unityContainer.RegisterType<HttpContextBase>(new InjectionFactory(c => new HttpContextWrapper(HttpContext.Current))); unityContainer.RegisterType<IOwinContext>(new InjectionFactory(c => c.Resolve<HttpContextBase>().GetOwinContext())); unityContainer.RegisterType<IAuthenticationManager>(new InjectionFactory(c => c.Resolve<IOwinContext>().Authentication));這個想法是 Unity 為
ApplicationSignInManager建構子提供與Create方法相同的依賴項。但是 Unity 的方法由於某種原因不起作用:成功登錄後沒有發送身份驗證 cookie。這是一個非常具體的問題,但也許有人以前遇到過這樣的問題?我相信這種行為應該與 OWIN 中間件、管道以及在應用程序啟動時如何連接所有這些東西有關。
不要
IOwinContext在容器中註冊,而是註冊 IAuthenticationManager:container.RegisterType<IAuthenticationManager>( new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));SignInManager 只有一個建構子:
public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)
以防萬一您還需要注入 RoleManager,以下是使用 Unity 完成的方法:
container.RegisterType<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>(new InjectionConstructor(typeof(MyDbContext)));不要忘記也註冊 IAuthenticationManager (見上面的答案)。