使用带有ASP.Net标识的Autofac将ApplicationUserManager传递给ApplicationOAuthProvider

use*_*333 6 dependency-injection inversion-of-control autofac asp.net-web-api asp.net-identity-2

我正在使用ASP.Net Identity并希望ApplicationUserManager通过以下文章将服务添加到我的所有自定义控制器:如何将我的Autofac容器插入ASP.NET Identity 2.1

这在我的控制器中完美运行,但是当我尝试通过在我的API上调用localhost:xxxx/token来创建令牌时.下面是调用的方法,但context.OwinContext.GetUserManager返回null.

我曾尝试注入ApplicationUserManagerApplicationOAuthProvider,但未能成功.你能指点我正确的方向吗?

编辑: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>();
Run Code Online (Sandbox Code Playgroud)

这让我可以把它传递给ApplicationUserManagerApplicationOAuthProvider的构造函数.在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
        };
Run Code Online (Sandbox Code Playgroud)

这让我更接近解决方案,但仍有两个问题.

第一种是当我在API上调用/ token时userManager.FindAsync(context.UserName, context.Password)返回null值,但userManager.FindByEmailAsync(context.UserName)返回正确的用户.我最初的想法是密码错误,但我确定它与我注册的密码相同.

第二个问题,如果我在我的AccountController上调用register,然后调用/ token,我得到一个无法访问已处置的对象.对象名称:'UserStore'错误.所以我认为这意味着我没有ApplicationOAuthProvider在我的Bootstrapper文件中正确初始化.

任何指导将不胜感激.谢谢!

His*_*ham 2

我终于找到了解决方案\n第一个解决方案: \n第一个:更改你的bootstrap autofac类\n你应该添加singleInstance(); 避免每个请求依赖项错误[没有与 \xe2\x80\x98AutofacWebRequest\xe2\x80\x99 匹配的标签的范围]

\n\n\n\n
   builder.RegisterType<DatabaseContext>().AsSelf().SingleInstance();\n   builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => new IdentityFactoryOptions<ApplicationUserManager>() { DataProtectionProvider = new DpapiDataProtectionProvider("your app name") });\n   builder.RegisterType<ApplicationUserManager>().AsSelf().SingleInstance();\n   // to resolve applicationUserManager  \n   builder.Register(c=>new ApplicationOAuthProvider(c.Resolve<ApplicationUserManager>())).AsImplementedInterfaces().SingleInstance();\n   builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<DatabaseContext>())).AsImplementedInterfaces().SingleInstance();\n   builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();\n
Run Code Online (Sandbox Code Playgroud)\n\n

第二:在 Startup.cs\n 中,将删除 GlobalConfiguration.configuration.DependencyResolver 因为它总是给出 null ..所以我将使用 autofac 容器解析器,但应该从 lifescope 使用它,这个容器从引导 autofac 配置方法返回

\n\n
OAuthOptions = new OAuthAuthorizationServerOptions\n    {\n        TokenEndpointPath = new PathString("/Token"),\n        Provider = container.BeginLifetimeScope().Resolve<IOAuthAuthorizationServerProvider>(),\n        AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),\n        AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),\n        AllowInsecureHttp = true\n    };\n
Run Code Online (Sandbox Code Playgroud)\n\n

第三:在您的ApplicationOAuthProvider类中将添加构造函数,以 applicationUserManager 作为参数

\n\n

这修复了我两天谷歌搜索后的空错误,但找不到答案,希望它有帮助。

\n\n

第二种解决方案:因为SingleInstance()不适合企业应用程序,所以您可以使用InstancePerRequest();对于所有寄存器类型

\n\n
   builder.RegisterType<DatabaseContext>().AsSelf().InstancePerRequest();\n   builder.Register<IdentityFactoryOptions<ApplicationUserManager>>(c => new IdentityFactoryOptions<ApplicationUserManager>() { DataProtectionProvider = new DpapiDataProtectionProvider("your app name") });\n   builder.RegisterType<ApplicationUserManager>().AsSelf().InstancePerRequest();\n   // to resolve applicationUserManager  \n   builder.Register(c=>new ApplicationOAuthProvider(c.Resolve<ApplicationUserManager>())).AsImplementedInterfaces().InstancePerRequest();\n   builder.Register(c => new UserStore<ApplicationUser>(c.Resolve<DatabaseContext>())).AsImplementedInterfaces().InstancePerRequest();\n   builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).As<IAuthenticationManager>();\n
Run Code Online (Sandbox Code Playgroud)\n\n

在 Startup.cs 中

\n\n
 OAuthOptions = new OAuthAuthorizationServerOptions\n    {\n        TokenEndpointPath = new PathString("/Token"),\n       // will instantiate new one to avoid Single Instance for resolving\n       Provider = new CustomOAuthProvider(new ApplicationUserManager(new UserStore<Entities.ApplicationUser>(new DataContext()),\n        AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),\n        AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),\n        AllowInsecureHttp = true\n    };\n
Run Code Online (Sandbox Code Playgroud)\n\n

CustomOAuthProvider 类

\n\n
using Microsoft.AspNet.Identity.Owin;\nusing Microsoft.Owin.Security;\nusing Microsoft.Owin.Security.OAuth;\nusing System.Security.Claims;\nusing System.Threading.Tasks;\n\npublic class CustomOAuthProvider:OAuthAuthorizationServerProvider\n{\n    private ApplicationUserManager _appUserManager;\n    public CustomOAuthProvider(ApplicationUserManager appUserManager)\n    {\n        this._appUserManager = appUserManager;\n    }\n\n\n\n    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)\n    {\n        var allowedOrigin = "*";\n\n        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { allowedOrigin });\n\n\n        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()));\n\n       AppUser user = await userManager.FindAsync(context.UserName, context.Password);\n\n        if (user == null)\n        {\n            context.SetError("invalid_grant", "Invalid username or password.");\n            return;\n        }\n        if (!user.IsActive)\n        {\n            context.SetError("invalid_activation", "Inactive account, contact support.");\n            return;\n        }\n\n        if (!user.EmailConfirmed)\n        {\n            context.SetError("invalid_grant", "User did not confirm email.");\n            return;\n        }\n\n\n        ClaimsIdentity oAuthIdentity = await userManager.GenerateUserIdentityAsync(user, "JWT");\n\n        AuthenticationTicket ticket = new AuthenticationTicket(oAuthIdentity, null);\n        context.Validated(ticket);\n\n    }\n\n\n    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)\n    {\n        if (context.ClientId == null)\n        {\n            context.Validated();\n\n        }\n\n        return Task.FromResult<object>(null);\n    }\n\n\n\n}\n
Run Code Online (Sandbox Code Playgroud)\n