这在我的控制器中完美运行,但是当我尝试通过在我的API上调用localhost:xxxx / token来创建令牌时.下面是调用的方法,但context.OwinContext.GetUserManager返回null.
我已经尝试将ApplicationUserManager注入到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();避免Per-Request Dependencies错误[没有标记匹配的范围’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>(),AllowInsecureHttp = true };
第三:在你的ApplicationOAuthProvider类中将添加构造函数取applicationUserManager作为参数
这个修复我的null错误后两天谷歌搜索,无法找到答案,希望它有所帮助.
第二个解决方案:因为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()),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); } }
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。