现有项目中的 IdentityServer3、Autofac、IdentityFramework
IdentityServer3, Autofac, IdentityFramework in existing project
我一直在研究 IdentityServer3,希望能取代我们当前的身份验证过程。
目前我们使用代码优先 entity framework 的自定义 identity framework 进程。
我设法安装了 IdentityServer3 并让 "in memory" 正常工作。现在我想把它连接到我们已经定制的 UserProvider
(UserManager
如果你喜欢的话)。
我们已经在使用 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
,但仍然出现相同的错误。
所以,我有几个问题:
- 这是分配 UserService 的正确方法吗?
- 这会允许我的现有用户进行身份验证吗?
- 以前有人做过吗?如果是这样,他们让它发挥作用了吗?
如果有人能帮我解决这些问题,我将不胜感激。
您解析 IdentityServerUserService
但您将 IdentityServerUserService
注册为 IUserService
。 Autofac 不会自动将类型注册为自身。
要修复错误,您可以将类型注册为自身
builder.RegisterType<IdentityServerUserService>()
.As<IdentityServer3.Core.Services.IUserService>()
.InstancePerDependency();
或解决IUserService
options.Factory.UserService = new Registration<IUserService>(scope.Resolve<IUserService>())
我一直在研究 IdentityServer3,希望能取代我们当前的身份验证过程。
目前我们使用代码优先 entity framework 的自定义 identity framework 进程。
我设法安装了 IdentityServer3 并让 "in memory" 正常工作。现在我想把它连接到我们已经定制的 UserProvider
(UserManager
如果你喜欢的话)。
我们已经在使用 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
,但仍然出现相同的错误。
所以,我有几个问题:
- 这是分配 UserService 的正确方法吗?
- 这会允许我的现有用户进行身份验证吗?
- 以前有人做过吗?如果是这样,他们让它发挥作用了吗?
如果有人能帮我解决这些问题,我将不胜感激。
您解析 IdentityServerUserService
但您将 IdentityServerUserService
注册为 IUserService
。 Autofac 不会自动将类型注册为自身。
要修复错误,您可以将类型注册为自身
builder.RegisterType<IdentityServerUserService>()
.As<IdentityServer3.Core.Services.IUserService>()
.InstancePerDependency();
或解决IUserService
options.Factory.UserService = new Registration<IUserService>(scope.Resolve<IUserService>())