9

Aggiungo la funzionalità di autenticazione Identità ASP.NET all'applicazione Web ASP.NET MVC 5.Injecting Dipendenza SignInManager: non funziona con Unity, funziona quando si utilizza OWIN

Sto usando l'Unità per l'iniezione di dipendenza in tutto il progetto, così ho deciso di iniettare le dipendenze richieste dal AccountController nel costruttore:

public AccountController(UserManager<ApplicationUser> userManager, SignInManager<ApplicationUser, string> signInManager) 
{ 
    _userManager = userManager; 
    _signInManager = signInManager; 
} 

Il mio metodo Login è implementato come segue (in realtà, ho copiato il codice da un modello ASP.NET Web Application progetto con l'autenticazione 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! 
} 

Il problema è che l'autenticazione non funziona correttamente - anche se sono entrato corretta creden tials e result è SignInStatus.Success, non ci sono cookie di autenticazione inviati nella risposta.

Tuttavia, se uso OWIN infrastrutture per risolvere ApplicationSignInManager invece di container Unità, tutto funziona correttamente:

// 
// 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! 
} 

Ecco come ApplicationSignInManager registrata in applicazione Startup classe:

app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create); 

E questo è ApplicationSignInManager dichiarazione:

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); 
    } 
} 

Ecco una parte della mia configurazione di 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)); 

L'idea è che l'Unità fornisce le stesse dipendenze al ApplicationSignInManager costruttore come Create metodo fa. Ma l'approccio di Unity non funziona per qualche motivo: nessun cookie di autenticazione viene inviato dopo il login riuscito.

Questa è una domanda molto specifica, ma forse qualcuno ha affrontato un problema come questo prima? Credo che questo comportamento dovrebbe essere correlato al middleware OWIN, alla pipeline e al modo in cui tutte queste cose vengono cablate all'avvio dell'applicazione.

risposta

13

Invece di registrare IOwinContext nel contenitore, non registrare IAuthenticationManager:

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

E avere un solo costruttore per SignInManager:

public ApplicationSignInManager(ApplicationUserManager userManager, IAuthenticationManager authenticationManager) 

ho fatto la registrazione con Unity like this, e qui è the explanation.

+0

Bene, il problema era nella mia configurazione di Unity: ho usato 'ContainerControlledLifetimeManager' invece del predefinito 'TransientLifetimeManager'. Ad ogni modo, il tuo articolo mi ha davvero aiutato a capirlo, quindi ho contrassegnato la tua risposta come accettata. Grazie per l'aiuto! –

+1

Articoli collegati fantastici! Vorrei averli trovati prima di perdere la maggior parte di ieri. Grazie! –

3

Nel caso sia necessario iniettare anche il RoleManager, qui ' s come è fatto con Unity:

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

Non dimenticare di registrare anche IAuthenticationManager (vedere la risposta sopra).

Problemi correlati