2

我需要从我的 web api 启动密码重置。我分别有身份服务器应用程序和 Web api 应用程序。我使用 OIDC 客户端与身份服务器进行通信。使用这个客户端,我只能调用登录、注销和一些标准方法。

我需要的是生成密码重置令牌并在 API 中获取重置令牌。

我试图'Microsoft.Extensions.Identity.Core'在我的 webapi 核心层中包含所有实体。但我明白了

尝试激活“Microsoft.AspNetCore.Identity.UserManager”时无法解析类型 Microsoft.AspNetCore.Identity.IUserStore1[Application.Core.Entities.User] 的服务

代码

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>>();

在我的 web api 中注入 UserManager 的正确方法是什么?

4

2 回答 2

2

您需要在 Web api 的 Startup 类中配置 asp.net 核心标识。不幸的是,您不能简单地调用services.AddIdentity(...ConfigureServices,因为在后台注册了基于 cookie 的身份验证方案并将其设置为默认质询方案,正如您在此处的 asp.net core 2.2此处的 asp.et core 3.1的代码中看到的那样. 因此,我最终得到的解决方案是复制和更新 AddIdentity 方法,如下所示:

对于 ASP.NET 核心 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 核心 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);
    }

然后,您应该在 Web api 应用程序的启动中调用 AddIdentityForWebApi。这将注册 UserManager,它现在将被注入到控制器的构造函数中。

然后您应该正确配置数据保护 API (DPAPI),以便您的 Web api 生成的令牌(当您_userManager.GeneratePasswordResetTokenAsync...从您的问题调用时)可以不受您的身份服务器应用程序的保护。

所以我在两个应用程序中设置了“DPAPI 应用程序名称”,两种ConfigureServices方法:

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

对于生产,在网络场环境中,您必须共享 DPAPI 密钥。根据您的情况,您有多种选择。

有关如何配置 DPAPI 的更多详细信息,请参阅官方文档。

我已经在运行 Windows 的 Kestrel 上进行了测试,我不确定 IIS。

于 2019-09-26T10:56:41.450 回答
0

注入代码看起来不正确。尝试将其更改为

services.AddScoped<UserManager<Application.Core.Entities.User>>();
于 2019-09-25T06:34:00.200 回答