Как вызвать метод UserManager IdentityServer из веб-API?

Мне нужно инициировать сброс пароля с моего веб-API. У меня есть приложение сервера идентификации и приложения веб-API отдельно. Я использую клиент OIDC для связи с сервером идентификации. С этим клиентом я могу вызывать только вход, выход и некоторые стандартные методы.

Мне нужно сгенерировать токен сброса пароля и получить токен сброса в API.

Я попытался включить 'Microsoft.Extensions.Identity.Core' в свой основной слой webapi, в котором есть все объекты. Но я получаю

Не удалось разрешить службу для типа Microsoft.AspNetCore.Identity.IUserStore1 [Application.Core.Entities.User] при попытке активировать Microsoft.AspNetCore.Identity.UserManager

код

private readonly UserManager<User> _userManager;

public AccountController(UserManager<User> userManager)
{
    _userManager = userManager;
}

private async Task<string> GeneratePasswordResetLinkAsync(User user)
{
    string token = await _userManager.GeneratePasswordResetTokenAsync(user);
    return token;
}

Я также пробовал добавить код ниже в инъекцию при запуске services.AddScoped<UserManager<User>, UserManager<User>>();

Как правильно внедрить UserManager в мой веб-API?


comment
Вы создаете собственный пользовательский класс, наследующий IdentityUser?   -  person Nan Yu    schedule 25.09.2019
comment
Как вы храните пользователей? Если вы используете удостоверение asp.net, у него уже должна быть возможность сбросить пароль пользователя, вам просто нужно попасть в правильную конечную точку из вашего веб-API.   -  person DaImTo    schedule 25.09.2019
comment
Нет, я использую существующий вызов пользователя объекта веб-API   -  person Ragavendhran N    schedule 26.09.2019
comment
Я использую vuex oidc. так как я провел некоторое исследование, я не смог найти какие-либо конечные точки для сброса пароля   -  person Ragavendhran N    schedule 26.09.2019


Ответы (2)


Вам необходимо настроить основной идентификатор asp.net в классе Startup вашего веб-API. К сожалению, вы не можете просто вызвать services.AddIdentity(... в ConfigureServices, потому что за кулисами схема аутентификации на основе файлов cookie регистрируется и устанавливается в качестве схемы проверки по умолчанию, как вы можете видеть в коде здесь или в здесь для ядра asp.et 3.1. Таким образом, решение, к которому я пришел, - это скопировать и обновить метод AddIdentity следующим образом:

Для ASP.NET CORE 2.2:

public static IdentityBuilder AddIdentityForWebApi<TUser, TRole>(
    this IServiceCollection services,
    Action<IdentityOptions> setupAction)
    where TUser : class
    where TRole : class
{
    // Hosting doesn't add IHttpContextAccessor by default
    services.AddHttpContextAccessor();

    // Identity services
    services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
    services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
    services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
    services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
    services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();

    // No interface for the error describer so we can add errors without rev'ing the interface
    services.TryAddScoped<IdentityErrorDescriber>();
    services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
    services.TryAddScoped<ITwoFactorSecurityStampValidator, TwoFactorSecurityStampValidator<TUser>>();
    services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
    services.TryAddScoped<UserManager<TUser>>();
    services.TryAddScoped<SignInManager<TUser>>();
    services.TryAddScoped<RoleManager<TRole>>();

    if (setupAction != null)
    {
        services.Configure(setupAction);
    }

    return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
}

Для ASP.NET CORE 3.1:

static IdentityBuilder AddIdentityForWebApi<TUser, TRole>(
      this IServiceCollection services,
      Action<IdentityOptions> setupAction)
      where TUser : class
      where TRole : class
    {
      // Hosting doesn't add IHttpContextAccessor by default
      services.AddHttpContextAccessor();

      // Identity services
      services.TryAddScoped<IUserValidator<TUser>, UserValidator<TUser>>();
      services.TryAddScoped<IPasswordValidator<TUser>, PasswordValidator<TUser>>();
      services.TryAddScoped<IPasswordHasher<TUser>, PasswordHasher<TUser>>();
      services.TryAddScoped<ILookupNormalizer, UpperInvariantLookupNormalizer>();
      services.TryAddScoped<IRoleValidator<TRole>, RoleValidator<TRole>>();

      // No interface for the error describer so we can add errors without rev'ing the interface
      services.TryAddScoped<IdentityErrorDescriber>();
      services.TryAddScoped<ISecurityStampValidator, SecurityStampValidator<TUser>>();
      services.TryAddScoped<ITwoFactorSecurityStampValidator, TwoFactorSecurityStampValidator<TUser>>();
      services.TryAddScoped<IUserClaimsPrincipalFactory<TUser>, UserClaimsPrincipalFactory<TUser, TRole>>();
      services.TryAddScoped<IUserConfirmation<TUser>, DefaultUserConfirmation<TUser>>();
      services.TryAddScoped<UserManager<TUser>>();
      services.TryAddScoped<SignInManager<TUser>>();
      services.TryAddScoped<RoleManager<TRole>>();

      if (setupAction != null)
      {
        services.Configure(setupAction);
      }

      return new IdentityBuilder(typeof(TUser), typeof(TRole), services);
    }

Затем вы должны вызвать AddIdentityForWebApi при запуске вашего веб-приложения api. Это зарегистрирует UserManager, и теперь он будет введен в конструктор вашего контроллера.

Затем вы должны правильно настроить Data Protection API (DPAPI), чтобы токен, сгенерированный вашим веб-API (когда вы вызываете _userManager.GeneratePasswordResetTokenAsync... из своего вопроса), мог быть незащищен вашим приложением сервера идентификации.

Итак, я установил "Имя приложения DPAPI" для двух приложений в обоих ConfigureServices методах:

services.AddDataProtection()
  .dataProtectionBuilder.SetApplicationName("YOUR_DPAPI_APPLICATION_NAME");

Для производства в среде веб-фермы вам придется поделиться ключами DPAPI. В зависимости от вашей ситуации у вас есть несколько вариантов.

См. официальную документацию. для получения дополнительных сведений о настройке DPAPI.

Я тестировал Kestrel под управлением Windows, я не уверен в IIS.

person Yanal-Yves Fargialla    schedule 26.09.2019
comment
@ ragavendhran-n, ты успел прочитать мой ответ? Я успешно использую это в своем проекте, и мне было бы интересно получить ваши отзывы. Что вы думаете? - person Yanal-Yves Fargialla; 04.10.2019
comment
@ ragavendhran-n, был ли мой ответ полезным / правильным? Я считаю, что мой ответ правильный. Если да, не могли бы вы отметить это как правильный ответ? - person Yanal-Yves Fargialla; 10.06.2020

Код инъекции выглядит некорректно. Попробуйте изменить его на

services.AddScoped<UserManager<Application.Core.Entities.User>>();
person Richard    schedule 25.09.2019