两因素 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的主要内容,如果未能解决你的问题,请参考以下文章

Google 身份验证器可作为公共服务使用吗?

使用 Gmail 等 Spring Security 的两因素身份验证

Sourcetree 添加具有两个因素身份验证的 bitbucket

.Net Core 中的两因素身份验证 - 如何验证令牌

如何将ansible与两因素身份验证一起使用?

Twilio SM 两因素身份验证