ASP.NET标识电子邮件验证令牌始终无效



我正在尝试实现一个邀请系统,在该系统中,新创建的帐户使用UserManager.GenerateEmailConfirmationToken和UserManager.ConfirmEmail通过电子邮件接收确认令牌。但是ConfirmEmail方法总是返回false。

根据这篇文章中的建议,我实现了我的MachineKeyDataProtector,并在Unity中注册如下:

container.RegisterType<IUserTokenProvider<User, Guid>, 
                       DataProtectorTokenProvider<User, Guid>>(new InjectionConstructor(new MachineKeyDataProtector("ASP.NET Identity")));

我的UserManager注入了IUserTokenProvider,如下所示:

public UserManager(IUserStore<User, Guid> store, IUserTokenProvider<User, Guid> userTokenProvider)
    : base(store)
{
    // Configure validation logic for passwords
    this.PasswordValidator = new PasswordValidator
    {
        RequiredLength = 6,
        RequireNonLetterOrDigit = false,
        RequireDigit = true,
        RequireLowercase = true,
        RequireUppercase = true,
    };
    this.UserTokenProvider = userTokenProvider;
}

然后,我将GenerateEmailConfirmationToken方法封装在一个扩展方法中:

public static string GenerateUrlForEmailConfirmationToken(this UserManager<User, Guid> userManager, UrlHelper urlHelper, Guid userId)
{
    var verificationCode = userManager.GenerateEmailConfirmationToken(userId);
    var url = urlHelper.Link(string.Empty, new
    {
        controller = "Account",
        action = "Verify",
        userId = userId,
        verificationCode = verificationCode
    });
    return url;
}

我正在使用它:

var url = UserManager.GenerateUrlForEmailConfirmationToken(Url, targetUser.Id);
//injects the url in a ready made html template
NotificationService.NotifyNewUser(targetUser, url);

调试GenerateUrlForEmailConfirmationToken我看到MachineKeyDataProtector的保护方法正在被调用,但是UserManager的ConfirmEmail从未调用MachineKeyDataPProtector的unprotect。

如果我更改DI配置以根据请求注册IUserTokenProvider

container.RegisterType<IUserTokenProvider<User, Guid>, 
                       DataProtectorTokenProvider<User, Guid>>(new PerRequestLifetimeManager(), 
                       new InjectionConstructor(new MachineKeyDataProtector("ASP.NET Identity")));

然后调用MachineKeyDataProtector的unprotect,但它会显示CryptographicException,并显示以下消息"加密操作过程中发生错误"。

这可能是验证总是错误的原因吗?如果是,如何确保调用unprotect方法?通过查看这两种情况下的对象,UserManager似乎使用了正确的IDataProtector。

感谢您的帮助!

我遇到了与您在示例SO文章中提到的问题相同的问题。我用它如下。在这种情况下,我使用SimpleInjector IOC来注册每个web请求的Usermanager

我认为您只需要创建新的DataProtectorTokenProvider,如果dataProtectionProvider中的任何一个都不存在。此外,在UserManager构造函数中包含DataProtectorTokenProvider创建将修复此问题。

private static void InitializeUserManager(ApplicationUserManager manager, IAppBuilder app)
        {
            manager.UserValidator = new UserValidator<AspNetApplicationUser>(manager)
            {
                AllowOnlyAlphanumericUserNames = false,
                RequireUniqueEmail = true
            };
            // Configure validation logic for passwords
            manager.PasswordValidator = new PasswordValidator
            {
                RequiredLength = 6,
                RequireNonLetterOrDigit = false,
                RequireDigit = true,
                RequireLowercase = true,
                RequireUppercase = true,
            };
            var dataProtectionProvider = app.GetDataProtectionProvider();
            if (dataProtectionProvider != null)
            {
                manager.UserTokenProvider = new DataProtectorTokenProvider<AspNetApplicationUser>(
                  dataProtectionProvider.Create("ASP.NET Identity"))
                {
                    TokenLifespan = TimeSpan.FromHours(3)
                };
            }
        }

我已经添加了令牌生命周期,但如果不需要,您可以删除它。

在试图弄清楚SignInManager.PasswordSignIn方法总是失败的原因后,发现问题是由于用户的SecurityStamp没有在本应设置的时候设置。

希望这能帮助其他人。

相关内容

  • 没有找到相关文章

最新更新