现有项目中的 IdentityServer3、Autofac、IdentityFramework

IdentityServer3, Autofac, IdentityFramework in existing project

我一直在研究 IdentityServer3,希望能取代我们当前的身份验证过程。 目前我们使用代码优先 entity framework 的自定义 identity framework 进程。 我设法安装了 IdentityServer3 并让 "in memory" 正常工作。现在我想把它连接到我们已经定制的 UserProviderUserManager 如果你喜欢的话)。

我们已经在使用 Autofac 并且我们的 UserProvider 注册如下:

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

我找到了一些说明 IdentityServer uses Autofac 本身的文档。 他们建议创建一个工厂,然后使用 IdentityServerOptions 注册用户服务,如下所示:

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

我遇到的问题是工厂看起来像这样:

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

它使用的是普通的 UserManager 而不是我们的自定义版本 and 它没有使用 DI 因为你在静态方法。 当然,使用 Autofac 会更好,因为我们已经注册了 UserProvider。 所以,我没有使用他们的 IdentityServerOptions 来调用静态方法。所以我把我的工厂改成这样:

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

我是这样在autofac中注册的:

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

然后我像这样分配给 IdentityServerOptions.Factory.UserService

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

我得到的范围是这样的:

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

我相信这应该可行,但是当我尝试使用邮递员进行身份验证时出现错误:

Autofac.Core.Registration.ComponentNotRegisteredException: The requested service 'Business.IdentityServerUserService' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

我尝试将 InstancePerDependency 更改为 InstancePerLifetimeScope,但仍然出现相同的错误。

所以,我有几个问题:

如果有人能帮我解决这些问题,我将不胜感激。

您解析 IdentityServerUserService 但您将 IdentityServerUserService 注册为 IUserService。 Autofac 不会自动将类型注册为自身。

要修复错误,您可以将类型注册为自身

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

或解决IUserService

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