1

J'ai joué avec IdentityServer3 dans l'espoir de remplacer notre processus d'authentification actuel. Actuellement, nous utilisons un processus de cadre d'identité personnalisé en utilisant l'infrastructure de première entité de code. J'ai réussi à installer IdentityServer3 et à faire fonctionner les choses "en mémoire". Maintenant, je veux raccorder à notre UserProvider déjà personnalisé (UserManager si vous aimez).IdentityServer3, Autofac, IdentityFramework dans le projet existant

Nous utilisons déjà Autofac et avons notre UserProvider enregistré comme ceci:

builder.RegisterType<UserProvider>().As<IUserProvider>().InstancePerDependency(); 

J'ai trouvé des documents indiquant que IdentityServer uses Autofac lui-même. Ils recommandent la création d'une usine, puis en utilisant IdentityServerOptions pour enregistrer le service utilisateur comme ceci:

options.Factory.UserService = new Registration<IUserService>(UserServiceFactory.Create()) 

Le problème que j'ai avec cela, est le ressemble à l'usine ceci:

public class UserServiceFactory 
{ 
    public static AspNetIdentityUserService<User, string> Create() 
    { 
     var context = new IdentityDbContext(); 
     var userStore = new UserStore<User>(context); 
     var userManager = new UserManager<User>(userStore); 

     return new AspNetIdentityUserService<User, string>(userManager); 
    } 
} 

qui utilise le UserManager normal plutôt que notre version personnalisée et il n'utilise pas DI parce que vous créez tout dans la méthode statique. Sûrement, il serait préférable d'utiliser Autofac car nous avons déjà enregistré UserProvider. Donc, je n'ai pas utilisé leur IdentityServerOptions pour appeler la méthode statique. Alors, je l'ai changé mon usine à ceci:

public class IdentityServerUserService : UserServiceBase 
{ 
    private readonly IUserProvider _userProvider; 

    public IdentityServerUserService(IUserProvider userProvider) 
    { 
     _userProvider = userProvider; 
    } 

    public override async Task AuthenticateLocalAsync(LocalAuthenticationContext context) 
    { 
     var user = await _userProvider.FindAsync(context.UserName, context.Password); 

     if (user != null && !user.Disabled) 
     { 
      // Get the UserClaims 

      // Add the user to our context 
      context.AuthenticateResult = new AuthenticateResult(user.Id, user.UserName, new List<Claim>()); 
     } 
    } 
} 

qui je me suis inscrit dans autofac comme ceci:

builder.RegisterType<IdentityServerUserService>() 
     .As<IdentityServer3.Core.Services.IUserService>() 
     .InstancePerDependency(); 

Et puis j'affecté au IdentityServerOptions.Factory.UserService comme ceci:

private static void SetupServices(IdentityServerOptions options, ILifetimeScope scope) 
{ 
    options.Factory.UserService = new Registration<IUserService>(scope.Resolve<IdentityServerUserService>()); 
} 

Et la portée Je reçois comme ceci:

var config = new HttpConfiguration(); 
var scope = config.DependencyResolver.GetRootLifetimeScope(); 

Je crois que cela devrait fonctionner, mais je reçois une erreur lorsque je tente d'utiliser postier pour authentifier:

Autofac.Core.Registration.ComponentNotRegisteredException: Le service demandé « Business.IdentityServerUserService » n'a pas été enregistré. Pour éviter cette exception, enregistrez un composant pour fournir le service, recherchez l'enregistrement du service à l'aide de IsRegistered() ou utilisez la méthode ResolveOptional() pour résoudre une dépendance facultative.

J'ai essayé de changer de InstancePerDependency à InstancePerLifetimeScope mais toujours eu la même erreur.

Donc, j'ai quelques questions:

  • Est-ce la bonne façon d'attribuer le UserService?
  • Est-ce que cela permettra à mes utilisateurs existants de s'authentifier?
  • Quelqu'un at-il déjà fait cela? Si oui, l'ont-ils fait fonctionner?

Si quelqu'un peut m'aider avec ces questions, je serais éternellement reconnaissant.

Répondre

1

Vous résolvez IdentityServerUserService mais vous enregistrez IdentityServerUserService en tant que IUserService. Autofac n'enregistre pas automatiquement le type comme lui-même.

Pour corriger l'erreur, vous pouvez enregistrer le type comme lui-même

builder.RegisterType<IdentityServerUserService>() 
     .As<IdentityServer3.Core.Services.IUserService>() 
     .InstancePerDependency(); 

ou résoudre IUserService

options.Factory.UserService = new Registration<IUserService>(scope.Resolve<IUserService>())