3

我允许新创建的用户谁知道他们的密码,并且尚未确认要更改他们的注册电子邮件(只要它没有在我的数据库中注册)如何撤销/无效/取消旧的电子邮件确认令牌(身份)

问题是,如果他们更改了电子邮件,我会生成新的电子邮件确认标记,但旧标记仍然可以验证它们(我在注册时发出的那个标记),这很可能意味着人们可以首先使用他们的注册邮件,将其更改为其他邮件他们无法访问,并从旧的验证,这是一个很大的安全漏洞,让我离开

有没有什么方法可以删除/撤销旧的令牌? (技术上我可以创建一个新用户并删除旧用户,旧的令牌不适用于新用户,但我认为应该有更好的解决方案)

回答

4

我将以下属性添加到我的ApplicationUser

public class ApplicationUser : IdentityUser { 
    public string EmailConfirmationToken { get; set; } 
    public string ResetPasswordToken { get; set; } 
} 

这会保留确认标记,以便在确认电子邮件标记时进行验证。

然后我将以下内容添加到我的ApplicationUserManager这是一个UserManager<ApplicationUser>派生类。

public override async System.Threading.Tasks.Task<string> GenerateEmailConfirmationTokenAsync(string userId) { 
    /* NOTE: 
    * The default UserTokenProvider generates tokens based on the users's SecurityStamp, so until that changes 
    * (like when the user's password changes), the tokens will always be the same, and remain valid. 
    * So if you want to simply invalidate old tokens, just call manager.UpdateSecurityStampAsync(). 
    */ 
    //await base.UpdateSecurityStampAsync(userId); 

    var token = await base.GenerateEmailConfirmationTokenAsync(userId); 
    if (!string.IsNullOrEmpty(token)) { 
     var user = await FindByIdAsync(userId); 
     user.EmailConfirmationToken = token; 
     user.EmailConfirmed = false; 
     await UpdateAsync(user); 
    } 
    return token; 
} 

public override async System.Threading.Tasks.Task<string> GeneratePasswordResetTokenAsync(string userId) { 
    var token = await base.GeneratePasswordResetTokenAsync(userId); 
    if (!string.IsNullOrEmpty(token)) { 
     var x = await FindByIdAsync(userId); 
     x.ResetPasswordToken = token; 
     await UpdateAsync(x); 
    } 
    return token; 
} 

public override async System.Threading.Tasks.Task<IdentityResult> ConfirmEmailAsync(string userId, string token) { 
    var result = await base.ConfirmEmailAsync(userId, token); 
    if (result.Succeeded) { 
     var x = await FindByIdAsync(userId); 
     x.EmailConfirmationToken = null; 
     await UpdateAsync(x); 
    } 
    return result; 
} 

public override async System.Threading.Tasks.Task<IdentityResult> ResetPasswordAsync(string userId, string token, string newPassword) { 
    var result = await base.ResetPasswordAsync(userId, token, newPassword); 
    if (result.Succeeded) { 
     var x = await FindByIdAsync(userId); 
     x.ResetPasswordToken = null; 
     await UpdateAsync(x); 
    } 
    return result; 
} 

添加了以下扩展程序,以便能够根据存储的令牌找到用户。

public static class ApplicationUserManagerExtension { 
    public static Task<string> FindIdByEmailConfirmationTokenAsync(this UserManager<ApplicationUser> manager, string confirmationToken) { 
     string result = null; 

     ApplicationUser user = manager.Users.SingleOrDefault(u => u.EmailConfirmationToken != null && u.EmailConfirmationToken == confirmationToken); 

     if (user != null) { 
      result = user.Id; 
     } 

     return Task.FromResult(result); 
    } 

    public static Task<string> FindIdByResetPasswordTokenAsync(this UserManager<ApplicationUser> manager, string token) { 
     string result = null; 

     ApplicationUser user = manager.Users.SingleOrDefault(u => u.ResetPasswordToken != null && u.ResetPasswordToken == token); 

     if (user != null) { 
      result = user.Id; 
     } 

     return Task.FromResult(result); 
    } 
} 
+1

在代码中的注释是我一直在寻找,更新安全印章废止旧令牌的解决方案,我只是发出新令牌之前使用它,这是辉煌的,谢谢! – mynameisjeff

相关问题