我最近遇到了下面的 Microsoft.Identity 类,它可以用作向登录的用户提供 2FA 生成和验证的一种方式,作为第二因素保护。我想知道是否有人找到了比以下示例更好的类或库或代码实践?
https://github.com/aspnet/Identity/blob/master/src/Core/AuthenticatorTokenProvider.cs
特别有问题的代码:
public virtual async Task<bool> ValidateAsync(string purpose, string token, UserManager<TUser> manager, TUser user)
{
var key = await manager.GetAuthenticatorKeyAsync(user);
int code;
if (!int.TryParse(token, out code))
{
return false;
}
var hash = new HMACSHA1(Base32.FromBase32(key));
var unixTimestamp = Convert.ToInt64(Math.Round((DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds));
var timestep = Convert.ToInt64(unixTimestamp / 30);
// Allow codes from 90s in each direction (we could make this configurable?)
for (int i = -2; i <= 2; i++)
{
var expectedCode = Rfc6238AuthenticationService.ComputeTotp(hash, (ulong)(timestep + i), modifier: null);
if (expectedCode == code)
{
return true;
}
}
return false;
}
我对上面的脚本不满意的原因是因为这个代码(据我测试过)不是一次性使用的,并且设置允许用户输入旧代码(在这个例子中最多 89 秒) ,如果i
在这种情况下将变量更改为 0,则意味着代码仅在 30s 内有效timestep
。
变量(在timestep
这种情况下)每 30 秒实时更新一次。因此,在 12:01:40,您可能已收到验证码,但这可能在 30 秒内“无效”,它仅在 19 秒内有效,直到下一个 30 秒timestep
更新。
您可能会争辩将时间步长增加到 3 分钟,但无论如何它仍然可能让用户在下一次timestep
更新之前请求代码。