如何防止在 MVC 2FA 中生成相同的 OTP

How to prevent generation of the same OTPs in MVC 2FA

MVC 2FA 有时会生成相同的 OTP(我已设置为 6 个数字),当您生成多个 OTP 时,可以使用以前的 OTP。 有没有办法生成唯一的 OTP 并禁用之前生成的 OTP?

 string code = await UserManager.GenerateTwoFactorTokenAsync(user.Id, provider);

这是OTP过期前设置的时间

app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(2));

OTP 是基于时间的,不会记录在任何地方。如果您在短时间内生成 2 个 OTP,您将获得相同的字符串。这就是算法的工作原理,没有 easy 绕过它的方法。

我今天偶然发现了这个 post 并找到了解决问题的简单方法。

https://www.stevejgordon.co.uk/asp-net-core-identity-token-providers

这 link 描述了在验证过程中使用了 SecurityTokenStamp 的事实。所以对我来说,每次我为用户发送 SMS 令牌时更新它是一件简单的事情。有效地使原来的无效。

  if(await userManager.UpdateSecurityStampAsync(user.Id) != IdentityResult.Success)
        {
            // https://www.stevejgordon.co.uk/asp-net-core-identity-token-providers
            // we update it to effectively reset all the token validation stuff
            return IdentityResult.Failed("failed to update the security stamp");
        }

        // Send token - this may throw but thats ok as we just rollback
        string code = await userManager.GenerateTwoFactorTokenAsync(user.Id, "twilio");
        await userManager.SmsService.SendAsync(new Microsoft.AspNet.Identity.IdentityMessage
        {
            Destination = user.UserName,
            Body = "Your security code is: " + code
        });

通过 UserManager.GenerateTwoFactorTokenAsync 生成的 OTP 不是一次性密码,尽管我们称它为 OTP。它是一个 TOTP(基于时间的一次性密码)。 https://en.wikipedia.org/wiki/Time-based_One-Time_Password

因此在特定时间段内生成的密码可能会更薄。 对于 SMS 和电子邮件,我注意到时间段约为 90 秒。这意味着它会在 90 秒内生成相同的密码。

对于身份验证器应用程序,也有此默认时间段。

通过围绕此进行大量研究,我注意到,要更改此默认时间段,我们需要创建自定义 2FA 令牌提供程序。