ASP.NET Identity 2中如何找到生成的密码重置令牌?

5
有没有办法在ASP.NET Identity 2中查看生成的密码重置令牌? 我的假设是,在TokenProvider中应该有一个字典,保存这些令牌在内存中。
更新:类似的问题:ResetPassword Token How and where is it stored? “令牌使用SecurityStamp生成,根据SecurityStamp验证,而不是在数据库或本地文件存储中存储。”
但问题仍然存在,框架如何知道令牌何时过期而不存储它?

@Nkosi 我能够生成令牌并使用它,但是为了调试目的,我需要查看内存中已经生成的令牌。我认为这是作为库的一部分自动完成的,我不需要将其存储在任何地方。 - Ehsan
令牌提供程序不会将生成的代码保存到内存中。 - Nkosi
@Nkosi 那么,当我使用生成的令牌调用ResetPassword时,它如何验证令牌? - Ehsan
2
潜在的重复?根据这个问题的答案,该值没有存储在任何地方。它是根据安全戳计算出来的... https://dev59.com/qYXca4cB1Zd3GeqPHFuc - Sam
1
@EhsanEsl Token提供程序有一个TimeSpan,用于计算生成的令牌是否已过期。 - Nkosi
显示剩余4条评论
2个回答

4

Token(令牌)不是存储在内存中的,而是从给定的 SecurityStamp 实时生成。 Token基本上是一个Unicode编码字符串。

您可以查看UserManager.csCreateSecurityTokenAsync方法。

internal async Task<byte[]> CreateSecurityTokenAsync(TUser user)
{
    return Encoding.Unicode.GetBytes(await GetSecurityStampAsync(user));
}

1

正如其中一位评论者所提到的:

“令牌是使用SecurityStamp生成的,并针对SecurityStamp进行验证,而不存储在数据库或本地文件存储中。”

这是从重置密码令牌如何存储和存储在哪里?引用的。

以下是我如何将令牌持久化以供以后使用的方法。

我假设您正在使用默认的项目模板。

ApplicationUser中创建属性以存储令牌。

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

AspNetUsers 表中创建相应的列。
然后,我按以下方式更新了 ApplicationUserManager 类。
    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);
        //associate the email token with the user account
        if (!string.IsNullOrEmpty(token)) {
            var x = await FindByIdAsync(userId);
            x.EmailConfirmationToken = token;
            x.EmailConfirmed = false;

            await UpdateAsync(x);
        }

        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;
    }

上述更改使我能够在会话之间持久化令牌。

这不是答案,因为我已经知道如何使用库,但我需要知道TokenProvider在哪里以及如何存储PasswordReset的令牌。 - Ehsan
2
从可扩展性的角度来看,我认为这很有帮助。我们不喜欢让用户再次输入电子邮件地址以“使用”重置链接。因此,存储最后创建的代码并通过它查找用户会有很大帮助。请注意:我们可能会在死硬的安全专家手中失去一些分数,但从用户体验专业人士那里赢得更多分数(这是一个平衡的行为)。 - timmi4sa
但你不需要要求用户提供他们的电子邮件 - 你只需将它嵌入到链接中,让他们点击即可。因此,你可以通过电子邮件发送包含?token=TOKEN&username=EMAIL的重置URL。既然这是你发送的电子邮件,那么我认为管理员会同意的。 - Simon_Weaver

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接