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

时间:2015-02-08 12:49:58

标签: c# asp.net-mvc asp.net-web-api asp.net-identity owin

我尝试实施一个邀请系统,其中新创建的帐户通过电子邮件使用UserManager.GenerateEmailConfirmationTokenUserManager.ConfirmEmail收到确认令牌。但是,ConfirmEmail方法始终返回false。

根据this帖子中的建议,我实现了我的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永远不会调用MachineKeyDataProtector的unprotect。

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

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

然后调用MachineKeyDataProtector的unprotect,但是它会删除CryptographicException并显示以下消息&#34;在加密操作期间发生错误。&#34;。

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

感谢任何帮助!

2 个答案:

答案 0 :(得分:1)

我遇到的问题与你在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)
                };
            }
        }

我已添加令牌生存时间,但如果不需要,您可以将其删除。

答案 1 :(得分:1)

在尝试找出为什么SignInManager.PasswordSignIn方法总是失败之后,发现问题是由于用户SecurityStamp未应该设置的原因而引起的。

希望这有助于其他人。