Dot-Net

注入 SignInManager 依賴項:不適用於 Unity,在使用 OWIN 時有效

  • September 11, 2015

我正在向 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!
}

問題是身份驗證無法正常工作 - 即使我輸入了正確的憑據並且resultSignInStatus.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中註冊的方式:Startup

app.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)

我已經像這樣在 Unity 中完成了註冊,這裡是解釋。

以防萬一您還需要注入 RoleManager,以下是使用 Unity 完成的方法:

container.RegisterType<IRoleStore<IdentityRole, string>, RoleStore<IdentityRole>>(new InjectionConstructor(typeof(MyDbContext)));

不要忘記也註冊 IAuthenticationManager (見上面的答案)。

引用自:https://stackoverflow.com/questions/26947371