生成仅包含小写字母和数字的唯一随机字符串

35

我该如何修复这段代码,以便它生成小写字母和数字的唯一随机组合?

api_string = (0...32).map{65.+(rand(25)).chr}.join    

目前,它只生成字母。


1
数字的范围是48到57。这些数字必须包含在您的范围内。 - soandos
谢谢你的回答。你能给一个例子让我标记为正确吗? - donald
12个回答

85

如果你正在使用 Ruby 1.9.2,你可以使用 SecureRandom:

irb(main):001:0> require 'securerandom'
=> true
irb(main):002:0> SecureRandom.hex(13)
=> "5bbf194bcf8740ae8c9ce49e97"
irb(main):003:0> SecureRandom.hex(15)
=> "d2413503a9618bacfdb1745eafdb0f"
irb(main):004:0> SecureRandom.hex(32)
=> "432e0a359bbf3669e6da610d57ea5d0cd9e2fceb93e7f7989305d89e31073690"

2
这对于简单的需求非常方便,但是 alpha 范围仅限于 a-f,因此生成的字符串的安全性/复杂性不如可能的高。 - John Bachir
5
最好使用内置的base64方式:SecureRandom.base64(16).gsub(/=+$/,'')。 - Michael Chaney
4
API 密钥方面没有问题,但也有一个很方便的方法叫 urlsafe_base64:SecureRandom.urlsafe_base64(16) => "XpMnLfc3FySd-C4V2Ipxag" - upasaka
8
更好的方式:SecureRandom.urlsafe_base64(length) - Dennis
@ckarbass Hex 只允许使用 0-9 和 a-f。Base64 使用更广泛的字符集。 - sscirrus
显示剩余2条评论

28

所有字母和数字都可以用36进制表示数字。

api_string = Array.new(32){rand(36).to_s(36)}.join

15

8次循环,每次从0到9和小写字母a到z中随机选取一个字符,并合并成字符串。


“'0'..'9'” 会生成从 0 到 9 的数组,“'a'..'z'” 会生成从 a 到 z 的数组,但每个字符前面的 * 到底是什么意思呢? - Vipin Verma
1
'0'..'9' 是一个范围,而 * 则是展开运算符。它将范围的元素拆分成单个项,并作为一组返回,因此基本上 * 帮助您分离元素,以便可以使用 sample 方法对其进行采样。 - Anuja Joshi
请查看此答案:https://dev59.com/4VnUa4cB1Zd3GeqPWgJF#72738840 - Touqeer

4
较新版本的Ruby支持SecureRandom.base58,相比于十六进制而言,使用它可以获得更密集的标记,且不包含任何特殊字符。请参考SecureRandom.base58了解更多信息。
> SecureRandom.base58(24)
> "Zp9N4aYvQfz3E6CmEzkadoa2" 

1
这个答案比被采纳的那个好多了。 - fsinisi90

2

我不记得是从哪里看到的,但今天早上我不知怎么看到了这个内容。

l,m = 24,36
rand(m**l).to_s(m).rjust(l,'0')

该技术会创建一个0到36的24次方之间的随机数,然后将其转换为基于36的字符串(即0-9和a-z)。


1
这比steenslag的https://gist.github.com/cameron-martin/a7a91f0bc952e8a5c795更快。 - Cameron Martin
1
除非 rand(36**len).to_s(36).length == len 一直成立,否则您需要执行 rand(36**len).to_s(36).rjust(len, '0') - Cameron Martin

2
这里有一种方法来实现它:
POSSIBLE = (('A'..'Z').to_a + (0..9).to_a)
api_string = (0...32).map { |n| POSSIBLE.sample }.join

如果您有Active Support可用,您还可以执行以下操作以创建类似API密钥的字符串:
ActiveSupport::SecureRandom.hex(32)

1
((('a'..'z').to_a + (0..9).to_a)*3).shuffle[0,(rand(100).to_i)].join

rand(100)替换为rand(n),其中n是所需字符串的最大长度。

1
CHARS = (?0..?9).to_a + (?a..?z).to_a
api_string = 32.times.inject("") {|s, i| s << CHARS[rand(CHARS.size)]}

1
这将生成一个包括数字和字母在内、长度在32到50个字符之间的小写随机字符串:
require 'string_pattern'

puts "32-50:/xN/".gen

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接