我尝试实施一个邀请系统,其中新创建的帐户通过电子邮件使用UserManager.GenerateEmailConfirmationToken和UserManager.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。
感谢任何帮助!
答案 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未应该设置的原因而引起的。
希望这有助于其他人。