【问题标题】:Generating GUIDs in Ruby在 Ruby 中生成 GUID
【发布时间】:2010-12-04 02:54:34
【问题描述】:

我有一个使用 GUID 很容易解决的问题。

特别是,对于密码重置工作流程,我想向用户的电子邮件发送一个 GUID 令牌,并让他们使用该令牌重置他们的密码。由于 GUID 是唯一的,因此这非常安全,并且可以节省我通过电子邮件向人们发送密码的风险。

我注意到有一个uuid gem @ rubyforge,但它看起来很旧,它会将内容写入文件系统。

有谁知道其他可以创建全球唯一标识符的 gem?

我知道我可以退回到:

(0..16).to_a.map{ |a| rand(16).to_s(16) }.join 

但它看起来并不像一个合适的 GUID ...

【问题讨论】:

  • 使用这样的随机字符串不太正确; UUID 中的某些位指定变体和版本。对于随机 UUID,您可能需要变体 2 (RFC 4122) 和版本 4,在这种情况下,必须将 6 个特定位设置为正确的值。
  • 是的@dafrazzman 是对的。随机拼凑“类似于 UUID”的东西并不能保证唯一性。虽然没有 UUID 是真正保证的,但使用随机数构建一个更容易发生冲突,并且不值得贴上“UUID”标签。绝对要使用 SecureRandom.uuid!

标签: ruby guid


【解决方案1】:

这是我从 JavaScript 中学到的一种技巧:

def uuid
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".gsub("x") do
        "0123456789ABCDEF"[rand(16)]
    end
end

尽管以更“红宝石的方式”也可以这样做:

def uuid
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".gsub("x") do
        rand(16).to_s(16)
    end
end

【讨论】:

    【解决方案2】:

    How to create small, unique tokens in Ruby

    >> require 'digest'
    => []
    >> Digest::SHA1.hexdigest("some-random-string")[8..16]
    => "2ebe5597f"
    
    >> SecureRandom.base64(8).gsub("/","_").gsub(/=+$/,"")
    => "AEWQyovNFo0" 
    
    >> rand(36**8).to_s(36)
    => "uur0cj2h"
    

    【讨论】:

      【解决方案3】:

      Simone Carletti 回答的小更新:

      SecureRandom.base64(8).gsub("/","_").gsub(/=+$/,"")

      => "AEWQyovNFo0"

      可以替换为:

      SecureRandom.urlsafe_base64(8)

      【讨论】:

        【解决方案4】:

        当我使用此问题中推荐的 uuid gem 时,没有人可以生成唯一且随机的 UUID。我的回答是变通,如果我们稍后有 gem 来满足请求,你最好在 Ruby 中使用 gem。

        我在这个问题中尝试了最推荐的 uuid gem,但没有人让我满意,我们需要唯一且随机的 uuid。我直接在ruby中运行系统命令uuidgen,结果我喜欢,在这里分享一下。

        puts `uuidgen`
        8adea17d-b918-43e0-b82f-f81b3029f688
        puts `uuidgen`
        6a4adcce-8f64-41eb-bd7e-e65ee6d11231
        puts `uuidgen`
        51d5348b-8fc3-4c44-a6f7-9a8588d7f08a
        puts `uuidgen`
        332a0fa3-7b07-41e1-9fc8-ef804a377e4e
        

        如果与uuid gem 比较,你就会知道其中的不同。

        irb(main):003:0> uuid.generate
        => "40cdf890-ebf5-0132-2250-20c9d088be77"
        irb(main):004:0> uuid.generate
        => "4161ac40-ebf5-0132-2250-20c9d088be77"
        

        测试环境为linux和Mac OS环境。

        【讨论】:

        • a puts `...` 基本上是在对 uuidgen(3) 进行系统调用,这在 Linux 以外的任何其他平台上都失败了,这会增加大量的执行时间,而且通常是非常违反直觉的编码实践。为什么会选择这样的方法?
        • @DwightSpencer 我认为我们在不同的领域有不同的目的。你关心的根本不是我关心的,比如执行时间、广泛的操作系统、代码迁移。我关心代码可以在 Mac OS 或主流 Linux 中运行并获得我需要的正确结果。当然,如果您可以在 Ruby 中找到一种方法并获得与 uuidgen 命令相同的结果,我很乐意使用它。但是直到现在,我都没有找到。
        • @J_ 和 @simone-carletti 都已经在这篇文章中指出了更好的方法。我会建议SecureRandom,因为它以与uuidgen 相同的方法执行相同的功能,但与uuidgen 仅使用阻塞/dev/random SecureRandom 不同,SecureRandom 首先使用openssl 的库,然后下降到dev /urandom 然后最后 /dev/random 尝试进行非阻塞随机化生成。
        【解决方案5】:

        从 Ruby 1.9 开始,uuid 生成是内置的。使用SecureRandom.uuid 函数。

        例如:

        require 'securerandom'
        SecureRandom.uuid # => "96b0a57c-d9ae-453f-b56f-3b154eb10cda"
        

        【讨论】:

        • SecureRandom.uuid 生成一个随机 UUID,因此不能保证它是唯一的。如果您只想要一个可能是唯一的随机字符串,则可以使用它。但是,如果您想要保证唯一的内容,则需要使用包含 MAC 地址、时间戳等的内容。
        • 为了节省您的查找时间,您需要 require 'securerandom'
        • 不能保证它是唯一的,但对于大多数实际用途,可以安全地假设它是唯一的。见:stackoverflow.com/questions/2977593/…
        • 如果 SecureRandom.uuid 按照文档所述遵循 RFC 4122,这是否意味着它具有时间戳字段?除非并发,这不就意味着唯一吗?
        • @MikeDotterer 没有 UUID 生成器可以保证唯一性。他们使用不同的方法使碰撞不太可能发生,但绝不是不可能的。
        【解决方案6】:

        创建一个正确的 mysql varchar 32 GUID

        SecureRandom.uuid.gsub('-','').upcase
        

        【讨论】:

        • SecureRandom.hex.upcase
        【解决方案7】:

        在深夜编程时,我想出了以下解决方案(基于 Simone 的),用于在 Rails 中生成唯一的 GUID。我并不为此感到自豪,但它确实运作良好。

        while Order.find_by_guid(guid = rand(36**8).to_s(36).upcase).present?; end
        

        【讨论】:

        • 我希望你记得那天晚上为你的 guid 列建立索引
        【解决方案8】:

        Google 生成以下 Ruby 库:

        http://raa.ruby-lang.org/project/ruby-guid/

        另外,在http://www.ruby-forum.com/topic/99262 他们说你可以安装一个gem(在命令行上执行gem uuid 来安装它)然后做

        gem 'uuid'
        puts UUID.new
        

        在您的代码中查看新的 UUID。

        (提示:我用 Google 搜索了 guid ruby​​

        【讨论】:

        • thx 我看到了,但它太旧了,只是在寻找一些活跃的东西,比如最近的宝石?
        • 我添加到答案中的 uuid gem 怎么样?还是你说的那个?
        • 这很奇怪......我也用谷歌搜索了“guid ruby​​”,我得到的只是这个 S.O.发布:-P
        【解决方案9】:

        你看UUIDTools了吗?

        UUIDTools 被设计成一个简单的库,用于生成各种类型的 UUID(或 GUID,如果您更喜欢这样称呼它们)。它尽可能符合 RFC 4122。

        【讨论】:

          猜你喜欢
          • 2011-07-26
          • 2011-03-11
          • 1970-01-01
          • 1970-01-01
          • 2012-05-16
          • 2011-03-03
          • 1970-01-01
          相关资源
          最近更新 更多