我正在使用GenerateEmailConfirmationTokenAsync生成令牌电子邮件确认链接,并使用ConfirmEmailAsync来验证链接。一切正常。
问题-链接只能运行一次。如果用户使用相同的链接,则第二次链接应该无效。我每次ConfirmEmailAsync IdentityResult.IsSucceded true时都进行调试和发现。我曾期望VerifyUserTokenAsync第二次返回false,但始终返回true。
请提出解决方案。谢谢
使用.Net Core 3.1,Identity Server 4
// To Generate Token
var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
// To Confirm Token
var result = await _userManager.ConfirmEmailAsync(user, code);
// Customised Token Provider
public class EmailConfirmationTokenProvider<TUser> : DataProtectorTokenProvider<TUser> where TUser : class
{
public EmailConfirmationTokenProvider(IDataProtectionProvider dataProtectionProvider,
IOptions<EmailConfirmationTokenProviderOptions> options, ILogger<EmailConfirmationTokenProvider<TUser>> logger)
: base(dataProtectionProvider, options, logger)
{
}
}
public class EmailConfirmationTokenProviderOptions : DataProtectionTokenProviderOptions
{ }
// Starup.cs Code
services.AddIdentity<ApplicationUser, IdentityRole>(options =>
{
options.Tokens.EmailConfirmationTokenProvider = "email_confirmation_provider";
options.SignIn.RequireConfirmedEmail = true;
})
.AddDefaultTokenProviders()
.AddTokenProvider<EmailConfirmationTokenProvider<ApplicationUser>>("email_confirmation_provider");
services.Configure<EmailConfirmationTokenProviderOptions>(options =>
{
options.TokenLifespan = TimeSpan.FromSeconds(3600);
});
答案 0 :(得分:3)
我认为您需要将ConfirmEmailAsync
的行为改写成这样,
如果令牌与已知用户匹配,表明该用户是有效发行的令牌。 然后将尝试与用户管理器确认令牌。 如果确认失败,则令牌已过期并且将采取适当的措施。
否则,如果令牌已确认,则会将其从关联用户中删除,从而使该令牌的重用无效。
public override async System.Threading.Tasks.Task<IdentityResult> ConfirmEmailAsync(string userId, string token) {
var user = await FindByIdAsync(userId);
if (user == null) {
return IdentityResult.Failed("User Id Not Found");
}
var result = await base.ConfirmEmailAsync(userId, token);
if (result.Succeeded) {
user.EmailConfirmationToken = null;
return await UpdateAsync(user);
} else if (user.EmailConfirmationToken == token) {
//Previously Issued Token expired
result = IdentityResult.Failed("Expired Token");
}
return result;
}
可以与密码重置类似。
方法2,尚未尝试,但请尝试一下, 确认完成后,尝试修改令牌的安全时间戳,以使令牌无效
UserManager.UpdateSecurityStampAsync(userId);