ruby-on-rails - 生成独特的,难以猜测的 “coupon”代码

标签 ruby-on-rails ruby algorithm uniqueidentifier

My Rails应用程序需要为用户生成电子优惠券。给定的每个优惠券都应具有唯一的优惠券代码,可以在我们的系统上兑换。

例如,免费墨西哥卷饼的优惠券。 User A收到免费卷饼的优惠券,然后User B收到免费卷饼的优惠券。 2张优惠券应具有唯一的优惠券代码。

生成像这样不容易伪造的代码的最佳方法是什么?我不希望用户输入随机数字和兑换其他人的优惠券的成功率很高。

我想我想找的是像礼品卡,背面有一个唯一的编号。

最佳答案

该代码必须不可猜测,因为在给用户奖励之前,您可以执行的唯一验证就是检查他们输入的代码是否在“已发布”代码列表中。

  • 这意味着该格式中所有可能的代码数都比您要发布的代码数大得多。根据简单地尝试代码的容易程度(例如脚本反复尝试),您可能需要所有可能的代码才能将已发布的代码数超过一百万或十亿甚至更多。听起来不错,但是在相对较短的琴弦中是可能的。
  • 这也意味着必须在所有可能的代码中尽可能随机地选择您使用的代码。避免用户弄清楚大多数有效代码都以“AAA”开头是必要的。更老练的用户可能会发现您的“随机”代码使用了可破解的随机数生成器(Ruby的默认rand()快速且统计上适用于随机数据,但是可以通过这种方式进行破解,因此请不要使用它)。

  • 此类安全代码的起点是加密PRNG的输出。 Ruby有securerandom库,您可以使用它来获得如下原始代码:
    require 'securerandom'
    SecureRandom.hex
    # => "78c231af76a14ef9952406add6da5d42"
    

    该代码足够长,可以覆盖任何实际数量的代金券(每个星球上每个人都有数百万个代金券),而没有任何有意义的重复机会或容易猜测的机会。但是,从物理副本中键入内容有点尴尬。

    一旦知道了如何生成随机的,几乎无法猜测的代码,您的下一个问题便是了解用户体验,并决定以可用性的名义实际上可以危及安全的程度。您需要牢记最终用户的值(value),因此要记住有人可能会努力获取有效代码。我不能为您回答这个问题,但是可以针对可用性提出一些一般性观点:
  • 避免歧义字符。在打印品中,有时很难看到1Il之间的区别。我们通常会从上下文中了解它应该是什么,但是随机字符串不具有此上下文。必须通过测试0O5S等来尝试几种代码变体,这将是糟糕的用户体验。
  • 使用小写或大写字母,但不能两者都使用。区分年龄的用户不会理解或区分大小写。
  • 匹配代码时接受变化。允许有空格和破折号。甚至允许0O表示同一意思。最好通过处理输入文本来做到这一点,以便在正确的情况下使用带分隔符的字符等。
  • 在打印中,将代码分成几个小部分,用户可以更轻松地找到他们在字符串中的位置并一次键入几个字符。
  • 不要使代码太长。我建议12个字符,分成3组,每组4个。
  • 这是一个有趣的示例-您可能希望扫描代码以查找可能的粗鲁单词,或者避免使用会生成粗鲁单词的字符。如果您的代码仅包含KUFC字符,那么冒犯用户的可能性就很大。通常不需要担心,因为用户看不到大多数计算机安全密码,但是这些密码会打印出来!

  • 综上所述,这就是我可能生成可用代码的方式:
    # Random, unguessable number as a base20 string
    #  .reverse ensures we don't use first character (which may not take all values)
    raw_string = SecureRandom.random_number( 2**80 ).to_s( 20 ).reverse
    # e.g. "3ecg4f2f3d2ei0236gi"
    
    
    # Convert Ruby base 20 to better characters for user experience
    long_code = raw_string.tr( '0123456789abcdefghij', '234679QWERTYUPADFGHX' )
    # e.g. "6AUF7D4D6P4AH246QFH"
    
    
    # Format the code for printing
    short_code = long_code[0..3] + '-' + long_code[4..7] + '-' + long_code[8..11]
    # e.g. "6AUF-7D4D-6P4A"
    

    有这种格式的20**12有效代码,这意味着您可以发布十亿个自己的代码,而用户仅猜测正确的代码就有四百万分之一的可能性。在密码学界,这是非常糟糕的(此代码对于快速的本地攻击是不安全的),但是对于向注册用户提供免费卷饼的网络表单,您会发现有人尝试使用脚本进行四百万次,这没关系。

    关于ruby-on-rails - 生成独特的,难以猜测的 “coupon”代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22333237/

    相关文章:

    c - 三角剖分算法

    ruby-on-rails - rails : controller#show logic for a link_to root_path or :back

    ruby-on-rails - 从数组中删除空白元素

    mysql - Rails、MySQL 和雪豹

    ruby - 使用 Ruby 通过 Outlook 发送消息的最简单方法是什么?

    ruby-on-rails - 如何在 Windows 上运行 Rails "script/[xyz]"命令?

    ruby - 在 Ruby 中将数据字段添加到其余客户端请求

    使无向图连通的算法

    algorithm - 布雷森纳姆圆算法

    css - Bootstrap 网格不能正常工作