在Ruby中生成向导


142

我有一些使用Guids可以轻松解决的问题。

特别是,对于密码重置工作流程,我想将Guid令牌发送到用户的电子邮件,并让他们使用该令牌重置密码。由于GUID是唯一的,因此这是非常安全的,并且省去了我用电子邮件向人们发送密码的麻烦。

我注意到Ruby 有一个Guid宝石;但它看起来很旧,并且将内容写入文件系统。

有谁知道其他可以创建全局唯一标识符的宝石?

我知道我可以回到:

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

但这似乎并不是一个合适的GUID ...


1
使用这样的随机字符串是不太正确的。UUID中的某些位指定了变体和版本。对于随机UUID,您可能需要版本2(RFC 4122)和版本4,在这种情况下,必须将6个特定位设置为正确的值。
jtpereyda

1
是的,@ dafrazzman是正确的。将“类似于UUID”的内容随机拼凑在一起并不能保证唯一性。虽然不能真正保证没有UUID ,但是使用随机数构建一个UU会更容易发生冲突,因此不值得使用标签“ UUID”。绝对要使用SecureRandom.uuid!
dooleyo 2013年

Answers:


312

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

例如:

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

5
SecureRandom.uuid生成随机UUID,因此不能保证它是唯一的。如果您只是想要一个可能唯一的随机字符串,则可以使用它。但是,如果您想保证某些东西是唯一的,则需要使用包括MAC地址,时间戳和其他内容的东西。
Mike Dotterer 2012年

23
为了节省您的查找时间,您需要提供“安全随机性”
Jesse Shieh

8
不能保证它是唯一的,但是出于大多数实际目的,可以肯定它是唯一的。请参阅:stackoverflow.com/questions/2977593/...
杰西Shieh

如果SecureRandom.uuid根据文档所述遵循RFC 4122,这是否意味着它具有时间戳字段?禁止并发,这是否意味着唯一?
迈克尔·麦迪逊

@MichaelKMadison AFAIK Ruby使用RFC 4122的“ v4”变体,该变体不使用时间戳,因此发生碰撞的机会实际上并不为零-但实际上,它的发生率也可能是
Edd Morgan


35

我们使用UUIDTools,并且没有问题。


2
即使系统没有MAC地址,“ uuidtools”也可以工作。在这种情况下,'uuid'失败。
grefab

3
与uuid gem不同,uuidtools不保留任何状态文件。状态文件的权限问题使uuid gem难以与多个用户一起使用。
韦恩·康拉德

1
似乎不再维护UUID工具。两年多来没有任何关于github回购的承诺
Sudhanshu Mishra

22

您看过UUIDTools吗?

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


16

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


我看到了,但是它已经很旧了,只是在寻找活跃的东西,比如最近的宝石?
兰斯·波拉德

我添加到答案中的uuid宝石怎么样?还是您所指的那个?
Marc W

5
太奇怪了……我也用Google搜索了“ guid ruby​​”,我只得到了这样的帖子:-P
Jason Whitehorn 2010年


3

小更新西蒙娜·卡莱蒂答案:

SecureRandom.base64(8).gsub(“ /”,“ _”)。gsub(/ = + $ /,“”)

=>“ AEWQyovNFo0”

可以替换为:

SecureRandom.urlsafe_base64(8)


1

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

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

2
我希望您记得那天晚上索引guid列
nurettin

0

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

在这个问题中,我尝试了大多数推荐的uuid宝石,但是没人能令我满意,我们需要唯一且随机的uuid。我直接uuidgen在ruby中运行系统命令,我喜欢结果,并在这里分享。

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宝石比较,您会知道其中的区别。

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环境。


2
a puts `...`基本上是在进行系统调用,uuidgen(3)但在Linux以外的任何其他平台上都失败了,这增加了执行时间,并且通常与直观的编码实践相反。为什么选择这种方法?
德怀特·斯潘塞

1
@DwightSpencer我认为我们在不同的领域具有不同的目的。您所关心的完全不在我关心的范围内,例如执行时间,广泛的操作系统,代码迁移。我关心代码可以在Mac OS或主流Linux中工作,并获得我需要的正确结果。当然,如果您可以在Ruby中找到一种方法并获得与uuidgen命令相同的结果,那么我很乐意使用它。但是直到现在,我还没有找到任何东西。
宝马

1
@J_和@ simone-carletti都已经在这篇文章中指出了一种更好的方法。我会建议,SecureRandom因为那是用相同的方法执行相同的功能,uuidgen但与的不同uuidgen,使用阻塞的/ dev / random仅首先SecureRandom使用openssl的库,然后放到dev / urandom,然后最后是/ dev / random尝试执行非阻塞随机化生成。
德怀特·斯潘塞

0

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

def uuid
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".gsub("x") do
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"[rand(36)]
    end
end

尽管也可以通过“更红宝石”的方式来做:

def uuid
    "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx".gsub("x") do
        rand(16).to_s(16)
    end
end
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.