6

Я использую ASP.Net Идентичность и хотел добавить ApplicationUserManager сервис для всех моих пользовательских контроллеров следуя эту статью: How to plug my Autofac container into ASP. NET Identity 2.1Переходя ApplicationUserManager к ApplicationOAuthProvider с Autofac с ASP.Net Идентичностью

Это прекрасно работает в моих контроллерах , но не тогда, когда я пытаюсь создать токен, вызывая localhost: xxxx/token на моем API. Ниже приведен метод, но context.OwinContext.GetUserManager возвращает null.

Я попробовал накинуть ApplicationUserManager на ApplicationOAuthProvider, но не смог ударить. Не могли бы вы указать мне в правильном направлении?

Edit: 10/15

Хорошо, таким образом я получил немного дальше, но я до сих пор stuck.I удалось инициализировать классы со следующим:

 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 я инициализировать поставщика с нижеследующим:

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, userManager.FindAsync(context.UserName, context.Password) возвращает нулевое значение, но userManager.FindByEmailAsync(context.UserName) возвращает нужного пользователя. Моя первоначальная мысль заключается в неправильном пароле, но я убедился, что это тот же пароль, который я зарегистрировал.

Второй вопрос, если я называю зарегистрироваться на моем AccountController, а затем вызвать/маркер, я получаю Не удается получить доступ к имени object.Object, расположенное: «» UserStore ошибки. Поэтому я предполагаю, что это означает, что я не инициализирую ApplicationOAuthProvider правильно в файле Bootstrapper.

Любое руководство будет принята с благодарностью. Благодаря!

+0

вы получите никакой радости с этим? У меня такая же проблема, когда я не могу ввести UserManager. Я использую Unity, но принцип тот же. – Raj

+0

Я не нашел полного решения, и, к сожалению, мне здесь не повезло. Я создал UserService и ввел ApplicationUserManager в эту службу, а затем ввел UserService в ApplicationOAuthProvider. Последнее, что я проверил, не получал ошибку объекта, но я все еще получал нулевое значение при вызове FindAsync() в UserManager. Надеюсь, это поможет. – user2325333

+0

yup, Im застрял точно в том же месте. Вы пробовали делать это без какой-либо инъекции? Я пытаюсь, но не могу, похоже, получить объект UserStore, который очень странный. – Raj

ответ

3

я, наконец, найти решения первое решение: первый: изменить класс начальной загрузки autofac вы должны добавить SingleInstance(); чтобы избежать Per-Request Dependencies ошибку [No Scope с Tag Matching '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, потому что его поддавки нуль всегда .. так я будешь использовать autofac контейнер распознаватель, но должны использовать его из lifetimescope, этот контейнер возвращается из вашей бутстраповской методы 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 в качестве параметра

это исправить мою ошибку null после двух дней поиска Google и не может найти ответ, надеюсь, что это поможет.

второе решение: потому что 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); 
    } 



} 
+0

Работал для меня, но не идеален, так как теперь я закодировал зависимость от моего IoC. Вы когда-нибудь изучали другие варианты? –

+0

Я обновил способ решения провайдера и отлично работает, вы можете проверить. – Hisham

Смежные вопросы