我最近遇到了下面的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,则意味着该代码仅在30秒的timestep
内有效。
CCD_ 3变量(在这种情况下(每30秒实时更新一次。所以在12:01:40,你本可以收到一个代码来验证,但这可能不是";有效的";对于30秒,它只有效19秒,直到下一个30秒的timestep
更新。
您可以主张将时间步长增加到3分钟,但无论如何,用户仍有可能在下一次timestep
更新之前请求代码。
通过一些挖掘,微软带来了这个"TOTP"2fa方法,它使用时间作为生成这些代码的方式,以及其他修饰符,如安全amp和哈希。
我找到的解决方案是保留此实现,但在用户成功验证后更新SecurityStamp,这也意味着必须刷新登录cookie。(因为登录cookie使用SecurityStamp生成,并且以相同的方式进行验证(
我宁愿偏离这个实现,而是使用一个更健壮的标准(适当的OTP(,但这个解决方案是有效的,并且仍然是一种有效的安全方法。