两因素 Google 身份验证与服务器上的代码不匹配 - ASP.Net MVC
Posted
技术标签:
【中文标题】两因素 Google 身份验证与服务器上的代码不匹配 - ASP.Net MVC【英文标题】:Two Factor Google Authentication not matching the codes on the server- ASP.Net MVC 【发布时间】:2015-09-13 16:51:20 【问题描述】:我在使用谷歌身份验证器的两因素身份验证中使用以下代码。 此验证的问题在于,谷歌身份验证器代码在我的本地机器上正确验证,而不是在服务器上。 服务器时间设置为:(UTC-05:00) 东部时间(美国和加拿大) 我的系统时间设置是:(UTC-06:00) Central Time (US & Canada)
在服务器上 - 当我尝试多次点击验证按钮时,它有时会正确验证有时不会。我不确定它为什么这样做。
任何人都可以帮助我提出解决此问题的想法/建议
public static class TimeBasedOneTimePassword
public static readonly DateTime UNIX_EPOCH = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private static MemoryCache _cache;
static TimeBasedOneTimePassword()
_cache = new MemoryCache("TimeBasedOneTimePassword");
public static string GetPassword(string secret)
return GetPassword(secret, GetCurrentCounter());
public static string GetPassword(string secret, DateTime epoch, int timeStep)
long counter = GetCurrentCounter(DateTime.UtcNow, epoch, timeStep);
return GetPassword(secret, counter);
public static string GetPassword(string secret, DateTime now, DateTime epoch, int timeStep, int digits)
long counter = GetCurrentCounter(now, epoch, timeStep);
return GetPassword(secret, counter, digits);
private static string GetPassword(string secret, long counter, int digits = 6)
return HashedOneTimePassword.GeneratePassword(secret, counter, digits);
private static long GetCurrentCounter()
return GetCurrentCounter(DateTime.UtcNow, UNIX_EPOCH, 30);
public static long GetCurrentRemaining()
return (long)(DateTime.UtcNow - UNIX_EPOCH).TotalSeconds % 30;
private static long GetCurrentCounter(DateTime now, DateTime epoch, int timeStep)
return (long)(now - epoch).TotalSeconds / timeStep;
public static bool IsValid(string secret, string password, int checkAdjacentIntervals = 1)
if (password == GetPassword(secret))
return true;
for (int i = 1; i <= checkAdjacentIntervals; i++)
if (password == GetPassword(secret, GetCurrentCounter() + i))
return true;
if (password == GetPassword(secret, GetCurrentCounter() - i))
return true;
return false;
【问题讨论】:
我删除了我之前的评论,即从不检查基础GetPassword(secret)
我现在看到它在 for 循环之前,我之前错过了 :) 你尝试过更高的检查相邻间隔吗?跨度>
我确实尝试为 checkAdjacentIntervals 设置 10,但是当我这样做时,它甚至成功验证了过去的代码,这意味着代码每 30 秒不断变化,因此过去 30 秒的代码也得到成功验证.我不确定这是否是正确的做法,因为它是一个两因素身份验证,我们只是出于安全目的进行额外验证。
确实如此,但我认为这是 checkAdjacentIntervals 的目的 - 考虑客户端和服务器之间的小时间差异。您可能可以将其缩小到 10 以下,但 1 可能还不够。这种双因素身份验证方法(不检查相邻间隔)将要求客户端和服务器都对时间有相同的理解......始终......在 30 秒的误差范围内。这似乎很难实现。
谢谢@Kritner。我听说 NTP 可以用来同步时间。你知道如何在服务器上使用它吗?
【参考方案1】:
我知道这是一个老问题,但它可能会帮助像我这样来寻找答案的其他人。 Google 身份验证基于时间工作。 API 将根据时间验证过去最近生成的代码(标记它,它是时间,而不是时区)。因此,如果系统的实际时间与生成代码的设备不同步,就会出现问题。特别是当系统时间落后于设备时间时。如果您想验证我的答案,请尝试输入一些较旧的代码(基于系统和设备之间的联系差距)。当您的系统领先于设备时,checkAdjacentIntervals 会为您提供帮助,但当它落后时则不会。
【讨论】:
【参考方案2】:我确实尝试将 checkAdjacentIntervals 设置为 5,我能够验证 google 身份验证器代码,但如前所述,它验证了过去的代码,这在我的情况下是不正确的。
所以我们通过使用 NTP 正确同步服务器的时间来更正服务器的时间,然后它开始按预期工作。
【讨论】:
以上是关于两因素 Google 身份验证与服务器上的代码不匹配 - ASP.Net MVC的主要内容,如果未能解决你的问题,请参考以下文章
使用 Gmail 等 Spring Security 的两因素身份验证