我正在使用ASP.Net Identity,并希望通过遵循以下文章将ApplicationUserManager
服务添加到我的所有自定义 Controller 中:How to plug my Autofac container into ASP. NET Identity 2.1
这在我的 Controller 中完美地工作,但是当我尝试通过在我的API上调用localhost:xxxx/token创建 token 时却无法正常工作。下面是调用的方法,但是context.OwinContext.GetUserManager
返回null。
我尝试将ApplicationUserManager
注入(inject)ApplicationOAuthProvider
,但未能成功。您能指出我正确的方向吗?
编辑:10/15
好的,虽然我走得更远了,但是我仍然很困惑,我能够使用以下方法初始化类:
var x = new DatabaseContext();
var store = new UserStore<ApplicationUser>(x);
var options = new IdentityFactoryOptions<ApplicationUserManager>()
{
DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ApplicationName")
};
builder.Register<DatabaseContext>(c => x);
builder.Register<UserStore<ApplicationUser>>(c => store).AsImplementedInterfaces();
builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => options);
builder.RegisterType<ApplicationUserManager>();
builder.Register<ApplicationOAuthProvider>(c => new ApplicationOAuthProvider("self", new ApplicationUserManager(store, options))).As<IOAuthAuthorizationServerProvider>();
这使我可以将
ApplicationUserManager
传递到ApplicationOAuthProvider
的构造函数中。在Startup.Auth
配置中,我使用以下代码初始化Provider:OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = (IOAuthAuthorizationServerProvider)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IOAuthAuthorizationServerProvider)),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
这使我更接近解决方案,但仍然有两个问题。
第一个是当我在API上调用/token时,
userManager.FindAsync(context.UserName, context.Password)
返回一个空值,但是userManager.FindByEmailAsync(context.UserName)
返回正确的用户。我最初的想法是密码错误,但是我确定密码与我注册时使用的密码相同。第二个问题是,如果我在AccountController上调用register,然后调用/token,则会收到无法访问已处置的对象。对象名称:'UserStore'错误。因此,我认为这意味着我没有在Bootstrapper文件中正确初始化
ApplicationOAuthProvider
。任何指导将不胜感激。谢谢!
最佳答案
我终于找到了解决方案
第一个解决方案:
首先:更改您的bootstrap autofac类
您应该添加singleInstance();避免每个请求的依赖关系错误 [无范围,且标签与'AutofacWebRequest'匹配的情况]
builder.RegisterType<DatabaseContext>().AsSelf().SingleInstance();
builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => new IdentityFactoryOptions<ApplicationUserManager>() { DataProtectionProvider = new DpapiDataProtectionProvider("your app name") });
builder.RegisterType<ApplicationUserManager>().AsSelf().SingleInstance();
// to resolve applicationUserManager
builder.Register(c=>new ApplicationOAuthProvider(c.Resolve<ApplicationUserManager>())).AsImplementedInterfaces().SingleInstance();
builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<DatabaseContext>())).AsImplementedInterfaces().SingleInstance();
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();
第二:在Startup.cs中
将会删除GlobalConfiguration.configuration.DependencyResolver,因为它总是始终为null ..所以我将使用autofac容器解析器,但应从lifetimescope中使用它,此容器是从您的bootstrap autofac配置方法返回的
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = container.BeginLifetimeScope().Resolve<IOAuthAuthorizationServerProvider>(),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
第三:在您的 ApplicationOAuthProvider 类中,将添加构造器以applicationUserManager作为参数
这修复了谷歌搜索两天后我的空错误,找不到答案,希望对您有所帮助。
第二种解决方案:因为 SingleInstance()不适用于企业应用程序,所以您可以使用 InstancePerRequest();所有registerTypes的
builder.RegisterType<DatabaseContext>().AsSelf().InstancePerRequest();
builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => new IdentityFactoryOptions<ApplicationUserManager>() { DataProtectionProvider = new DpapiDataProtectionProvider("your app name") });
builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();
// to resolve applicationUserManager
builder.Register(c=>new ApplicationOAuthProvider(c.Resolve<ApplicationUserManager>())).AsImplementedInterfaces().InstancePerRequest();
builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<DatabaseContext>())).AsImplementedInterfaces().InstancePerRequest();
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();
在Startup.cs中
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
// will instantiate new one to avoid Single Instance for resolving
Provider = new CustomOAuthProvider(new ApplicationUserManager(new UserStore<Entities.ApplicationUser>(new DataContext()),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
AllowInsecureHttp = true
};
CustomOAuthProvider类
using Microsoft.AspNet.Identity.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.OAuth;
using System.Security.Claims;
using System.Threading.Tasks;
public class CustomOAuthProvider:OAuthAuthorizationServerProvider
{
private ApplicationUserManager _appUserManager;
public CustomOAuthProvider(ApplicationUserManager appUserManager)
{
this._appUserManager = appUserManager;
}
public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
{
var allowedOrigin = "*";
context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });
var userManager = new ApplicationUserManager(new Microsoft.AspNet.Identity.EntityFramework.UserStore<AppUser>(new Data.DataContext()),new IdentityFactoryOptions<ApplicationUserManager>(),new Data.Repositories.SettingRepository(new Data.Infrastructure.DbFactory()));
AppUser user = await userManager.FindAsync(context.UserName, context.Password);
if (user == null)
{
context.SetError("invalid_grant", "Invalid username or password.");
return;
}
if (!user.IsActive)
{
context.SetError("invalid_activation", "Inactive account, contact support.");
return;
}
if (!user.EmailConfirmed)
{
context.SetError("invalid_grant", "User did not confirm email.");
return;
}
ClaimsIdentity oAuthIdentity = await userManager.GenerateUserIdentityAsync(user, "JWT");
AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, null);
context.Validated(ticket);
}
public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
{
if (context.ClientId == null)
{
context.Validated();
}
return Task.FromResult<object>(null);
}
}
关于asp.net-web-api - 使用具有ASP.Net Identity的Autofac将ApplicationUserManager传递给ApplicationOAuthProvider,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26371214/