2015-02-08 111 views
1

我试图通过使用UserManager.GenerateEmailConfirmationTokenUserManager.ConfirmEmail通过电子邮件实现新创建的帐户收到确认令牌的邀请系统。但是ConfirmEmail方法总是返回false。ASP.NET身份验证令牌电子邮件始终无效

按在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的保护方法被调用,但是MachineKeyDataProtector的解除是永远不会的UserManager的ConfirmEmail调用。

如果我改变DI配置到每个请求

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

然后MachineKeyDataProtector的解除被称为注册IUserTokenProvider但trows以下消息一个CryptographicException“加密操作过程中出现错误。”

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

任何帮助表示赞赏!

回答

1

在试图弄清楚为什么SignInManager.PasswordSignIn方法总是失败以及发现问题是由于用户的SecurityStamp应该已经被设置而没有被设置。

希望这可以帮助别人。

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

这是正确的。 'DataProtectionTokenProvider'必须是单身人士。其中一个加密密钥是每次创建对象时生成的guid。 – trailmax 2015-02-08 15:02:37

+0

该示例显示正在使用默认IDataProtector,这不是按照http://stackoverflow.com/questions/23455579/generating-reset-password-token-does-not-work-in-azure -网站 – JCS 2015-02-08 16:06:56