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

相關問題