给定长度的完全随机标识符

时间:2011-07-07 17:40:05

标签: ruby-on-rails ruby ruby-on-rails-3

我想生成一个完全随机的“唯一”(我将确保使用我的模型)给定的标识符(长度可能不同)长度包含数字,字母和特殊字符

例如:

161551960578281|2.AQAIPhEcKsDLOVJZ.3600.1310065200.0-514191032|

有人可以在Ruby on Rails中建议最有效的方法吗?

编辑:重要提示:     如果可能,请评论您提出的解决方案的效率,因为每次用户进入网站时都会使用此解决方案!

由于

6 个答案:

答案 0 :(得分:12)

将此用作访问令牌与UUID不同。您不仅需要伪随机性,还需要加密安全PRNG。如果你真的不关心你使用的是什么字符(它们没有向安全性添加任何内容),你可以使用以下内容,生成一个URL安全的Base64编码的访问令牌。如果将令牌附加到URL,URL安全性就变得很重要,类似于某些Java Web应用程序所做的那样:“http://www.bla.com/jsessionid=”。如果您为此目的使用原始Base64字符串,则会产生可能无效的URL。

require 'securerandom'

def produce_token(length=32)
  token = SecureRandom.urlsafe_base64(length)
end

获得重复的概率等于2 ^( - 长度)。由于输出将采用Base64编码,因此实际输出长度为4/3 *。如果已安装,则基于本机OpenSSL PRNG实现,因此在性能方面应该非常高效。如果没有安装OpenSSL扩展,如果可用,将使用/dev/urandom,最后,如果您在Windows计算机上,CryptGenRandom将用作后备。这些选项中的每一个都应该具有足够的性能。例如,在我的笔记本电脑上运行produce_token一百万次完成~6s。

答案 1 :(得分:3)

Universally Unique Identifieres - UUIDs生成自己很棘手;-)如果您想要真正可靠的内容,请使用uuid4r gem并将其与UUID4R::uuid(1)一起调用。这将根据时间和硬件ID(计算机mac地址)吐出一个uuid。因此,如果在同一时间生成,它在多台机器上甚至是唯一的。

uuid4r的要求是ossp-uuid c library,您可以使用自己选择的数据包管理器进行安装(例如,apt-get install libossp-uuid libossp-uuid-dev在debian上或brew install ossp-uuid在mac上,homebrew或者通过手动下载和编译当然。

使用uuid4r而不是手动(更简单?)实现的优势在于它是a)真正独特的,而不仅仅是某种伪随机数生成器,有时是可靠的"和b)通过使用c库的原生扩展来快速(即使使用更高的uuid版本)

require 'rubygems'
require 'uuid4r'
UUID4R::uuid(1) #=> "67074ea4-a8c3-11e0-8a8c-2b12e1ad57c3"
UUID4R::uuid(1) #=> "68ad5668-a8c3-11e0-b5b7-370d85fa740d"

更新: 关于速度,请参阅我的(完全不科学!)超过50k迭代的小基准

      user     system      total        real
version 1  0.600000   1.370000   1.970000 (  1.980516)
version 4  0.500000   1.360000   1.860000 (  1.855086)

所以在我的机器上,生成一个uuid需要大约0.4毫秒(请记住,我在整个基准测试中使用了50000次迭代)。希望你的速度足够快

(遵循"基准")

require 'rubygems'
require 'uuid4r'
require 'benchmark'

n = 50000
Benchmark.bm do |bm|
  bm.report("version 1") { n.times { UUID4R::uuid(1) } }
  bm.report("version 4") { n.times { UUID4R::uuid(4) } }
end

heroku更新:gem是available on heroku as well

答案 2 :(得分:3)

最佳解决方案是:

require 'active_support/secure_random'
ActiveSupport::SecureRandom.hex(16) # => "00c62d9820d16b52740ca6e15d142854"

这将生成加密安全的随机字符串(即完全不可预测)

同样,您可以使用库来生成其他人建议的UUID。在这种情况下,请务必使用随机版本(版本4)并确保实现使用cryptosecure随机生成器。

与安全相关的任何内容,滚动自己并不是最好的主意(即使我也屈服于它,请看第一版!:-)。如果确实想要一个自制的随机字符串,这里重写了tybro0103的方法:

require 'digest/sha1'
ALPHABET = "|,.!-0123456789".split(//) + ('a'..'z').to_a + ('A'..'Z').to_a

def random_string
    not_quite_secure = Array.new(32){ ALPHABET.sample }.join
    secure = Digest::SHA1.hexdigest(not_quite_secure)
end

random_string # => "2555265b2ff3ecb0a13d65a3d177b326733bc143"

请注意,它会散列随机字符串,否则可能会受到攻击。 表现应该类似。

答案 3 :(得分:2)

def random_string(length=32)
    chars = (0..9).to_a.concat(('a'..'z').to_a).concat(('A'..'Z').to_a).concat(['|',',','.','!','-'])
    str = ""; length.times {str += chars.sample.to_s}
    str
end

结果:

>> random_string(42)
=> "a!,FEv,g3HptLCImw0oHnHNNj1drzMFM,1tptMS|rO"

答案 4 :(得分:0)

由于字符行为的改变,在Ruby 1.9和1.8中生成随机字母有点棘手。在1.9中执行此操作的最简单方法是生成要使用的字符数组,然后从该数组中随机抓取字符。 见http://snippets.dzone.com/posts/show/491

答案 5 :(得分:0)

您可以查看我使用here一个

的实施this