注入SignInManager依赖项:不能与Unity一起使用,在使用OWIN时有效

时间:2014-11-15 15:25:32

标签: .net asp.net-mvc dependency-injection asp.net-identity owin

我正在向ASP.NET MVC 5 Web应用程序添加ASP.NET身份验证功能。

我在整个项目中使用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。

但是,如果我使用OWIN基础结构来解析ApplicationSignInManager而不是Unity容器,那么一切正常:

//
// 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中间件,管道以及在应用程序启动时如何连接所有内容有关。

2 个答案:

答案 0 :(得分:13)

不是在容器中注册IOwinContext,而是注册IAuthenticationManager:

container.RegisterType<IAuthenticationManager>(
                new InjectionFactory(c => HttpContext.Current.GetOwinContext().Authentication));

只有一个SignInManager构造函数:

public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager)

我已经完成了对Unity like this的注册,这里是the explanation.

答案 1 :(得分:3)

以防万一你需要注入RoleManager,这是Unity如何完成的:

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

不要忘记注册IAuthenticationManager(参见上面的答案)。