【问题标题】:GenerateChangePhoneNumberToken method in ASP.NET identity generates duplicate security codeASP.NET 标识中的 GenerateChangePhoneNumberToken 方法生成重复的安全代码
【发布时间】:2016-02-17 15:08:53
【问题描述】:

我们在 MVC 应用程序中使用 ASP.net 身份。每当用户更改电话号码或密码时,我们将通过电子邮件或SMS 向用户发送安全代码。我们将对用户验证安全码,如果有效,我们将允许用户更改电话号码或密码。

我们正在使用ASP.net身份提供的GenerateChangePhoneNumberToken方法生成安全码。

var securityCode = UserManager.GenerateChangePhoneNumberToken(
                                                user.Id, model.MobileNumber);   

HTML

   <div class="text-center top-space" id="validate_code_email">
      <button id="send_via_email" class="submit-btn login-btn-align material_button" data-role="button" onclick="sendCodeViaEmail()">Send a New Code Via Email</button>
   </div>

jQuery

 function sendCodeViaText() {          
        var model = { 'UserId': userIdentityId };
        $.ajax({
            url: "/api/accountwebapi/SendVerificationEmail",
            type: "POST",
            data: model,
            dataType: "json",
            success: function (data) {

            },
            error: function (e) {

            }
        });

发送安全码的API控制器方法

  public IHttpActionResult SendVerificationEmail([FromBody] VerifyPhoneNumberViewModel model)
  {
       try
       {
           if (model != null)
           {
               var user = UserManager.Users.Where(a => a.Id == model.UserId).FirstOrDefault();
               if (user != null)
               {
                   var code = UserManager.GenerateChangePhoneNumberToken(
                                                                 user.Id, user.PhoneNumber);
                   UserManager.SendEmail(user.Id,
                                "Confirm your account",
                                                        "Your security code is: " + code);
                   return Ok(new { success = true, PhoneNumber = user.PhoneNumber, UserId = user.Id, message = C.RESENDVERIFICATIONCODEEMAILSUCCESS });
               }
           }
           else
           {
               return Ok(new { success = true, message = C.RESENDVERIFICATIONCODEEMAILSUCCESS });
           }
           return Ok(new { success = false, message = C.TRYAGAIN });
       }
       catch (Exception e)
       {
           LogError(e.Message, e);
           throw;
       }
   }

我们在生成和验证安全代码方面没有问题。我们面临的唯一问题是GenerateChangePhoneNumberToken 方法生成重复代码。

Click one - Security Code : 123456 User ID : 1 

Click two - Security Code : 123456 User ID : 1 

一分钟后它会生成不同的代码

Click three Security Code : 123457 User ID : 1 

因此,如果用户连续单击它会生成重复的安全代码。如何预防这个问题?请帮忙...

【问题讨论】:

  • 你有 Click 事件处理程序的代码吗?
  • 是的,点击按钮后,我们将生成安全代码,并将其发送给经过身份验证的用户到他的电子邮件或电话
  • 我的意思是,您能否在问题中至少显示其中的某些部分,尤其是安全代码是如何递增的。至于安全性是如何产生的,你可以选择不显示,但如果不是太敏感,如果也能在问题中显示就好了。这样,问题可能更容易被发现。
  • GenerateChangePhoneNumberToken 中提到的方法是 asp.net identity 提供的一种内置方法,我也不知道它是如何生成安全代码的......
  • 不,不。我的意思是Click 方法……你有吗?

标签: c# asp.net-mvc asp.net-identity


【解决方案1】:

这是设计使然。用于电话确认的安全令牌取决于用户记录、电话号码和时间上的SecurityStamp。鉴于电话号码和安全印章未更改,您将每 3 分钟获得一次新代码。

参见source code,方法public static int GenerateCode(SecurityToken securityToken, string modifier = null)。甚至还有评论// Allow a variance of no greater than 90 seconds in either direction
如果你深入代码,你会或多或少得到这个sn-p:

DateTime _unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
TimeSpan _timestep = TimeSpan.FromMinutes(3);

var delta = DateTime.UtcNow - _unixEpoch;
var currentTimeStep = (ulong)(delta.Ticks / _timestep.Ticks);

而且时间步长仅每 3 分钟更改一次。

如果生成多个相同的确认代码是个问题,我建议您更改 UI 以防止这种情况发生 - 一旦发送代码,禁用或删除要求执行此操作的按钮。从讨论中我了解到这是通过 ajax 请求在客户端完成的 - 这应该不是一个主要问题。

【讨论】:

  • 我们向用户提供了按钮,这样如果他没有在电子邮件或电话中收到安全码,他将单击该按钮以再次接收代码。那么,我无法更改 UI,是否有解决此问题的方法?
  • 为你点赞,因为至少我知道了这个问题背后的原因
  • 好吧,为什么你认为两次接收相同的代码会有问题?每次发送此邮件时,您都可以在用户上更新 SecurityStamp - 这将为您提供不同的确认码。但这可能会导致更多问题:第一条消息有延迟,因此用户要求发送第二条消息。第一条消息到达,用户尝试使用第一条消息进行确认,但它不再有效,因为 SecurityStamp 已更改 => 沮丧和更多发送的代码。
  • 发送和验证安全代码,除了相同的代码问题外,功能工作正常。我不想通过更改安全标记来引入更多问题。将对此进行更多分析...
  • 是的,真正的问题 - 发出的相同代码是问题还是优势。想想看。在我运行的一些系统中,我从未遇到过这样的问题,但设置和意图与您在此处描述的相同。
猜你喜欢
  • 2013-11-29
  • 2015-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-10
  • 2011-04-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多