Perl随机字符串,但在浏览器中使用时看起来并不随意

时间:2017-10-19 11:41:18

标签: perl random

这让我疯了!我有一个需要创建随机ID的脚本,以便可以重命名该文件。这是我的测试:

for (my $i = 0; $i <= 100; $i++) {
    my $test = rand_id();
    print "FOO: $test\n";
}

sub rand_id {
# Used for the file names (not temp_id, for new adds)
  use String::Random qw(random_regex random_string);
  my $rand = random_regex("[a-zA-Z0-9]"x20);
  return $rand;
}

这正如我所希望的那样:

root@admin:# perl test.cgi
FOO: P2kyuotdlk04gcafvoze
FOO: ZGC44tXfGFaiXeHsLZdn
FOO: fydWFp1PW6iGYFaOfgvx
FOO: xG4SPx2gLGPVeMJOupZ9
FOO: 6A2uD9hCF90VP7ybKjiA
FOO: wT4fG8ogmV37Mkljs0gE
FOO: 6QttcmlNjO1o9jCVht3g
FOO: 9bAYYDd2NIjBWgAhsl3t
FOO: hrU04kHvxu0JJYPHv6Jk
FOO: 9EVL9GqGdWWZhDam6dc9
FOO: F0zruszqvmMOUumlO4Q1
FOO: KA9jOof9iSTxpDOWUMBl
FOO: phicMiogMhZIcPZiXvj8
etc

所以好(没有重复)。

然后我的脚本中有几乎相同的代码(只是不在循环中),但是当我从浏览器继续重新加载时,我得到:

NEW: 0ab3K60sJSpHrvDVCKcR
NEW: 0ab3K60sJSpHrvDVCKcR
NEW: 0ab3K60sJSpHrvDVCKcR
NEW: 0ab3K60sJSpHrvDVCKcR
NEW: 0ab3K60sJSpHrvDVCKcR
NEW: EyiYp5D6d8CL3vzozYFZ
NEW: EyiYp5D6d8CL3vzozYFZ
NEW: EyiYp5D6d8CL3vzozYFZ
NEW: EyiYp5D6d8CL3vzozYFZ
NEW: EyiYp5D6d8CL3vzozYFZ
NEW: A0KUBiNSDcxyX7JQzBsk
NEW: A0KUBiNSDcxyX7JQzBsk
NEW: A0KUBiNSDcxyX7JQzBsk
NEW: A0KUBiNSDcxyX7JQzBsk
NEW: A0KUBiNSDcxyX7JQzBsk
NEW: 7wU3RgK1Ho16rEjkGSsB
NEW: 7wU3RgK1Ho16rEjkGSsB
NEW: 7wU3RgK1Ho16rEjkGSsB

正如你所看到的,有很多重复的&#34;随机&#34; IDS。我做错了什么?

我正在使用的模块是http://search.cpan.org/~steve/String-Random-0.20/Random.pm,但在做某些事情时,我遇到同样的问题:

my $rand = Digest::MD5::md5_base64( rand );

1 个答案:

答案 0 :(得分:5)

您可能会获得不合适的ID的原因有很多:

  • 服务器或浏览器可能正在缓存响应(在这种情况下不太可能,但总是值得调查)。

  • 随机数生成器在服务器进程中初始化,然后为每个请求分配一个工作进程。然后,工作进程继承RNG状态。对于普通的CGI,这是不太可能的,因为为每个请求分叉并执行了一个新进程。

  • 用弱种子初始化随机数发生器,例如srand(time)。由于time()具有1秒的分辨率,因此您将在一秒钟内为所有进程获取相同的种子。除非您想获得可重复的“随机”数字序列,否则不建议手动初始化srand()

  • 内置random()功能可能使用低质量算法。它绝对不适合加密目的。使用保证特定PRNG的模块,并使用适当的熵源播种。

  • 随机数可能会多次出现。对于真正的随机性,您可以使用Birthday Paradox计算碰撞概率。除非碰撞概率在天文数字上很小,否则您的应用程序需要能够避免重复ID。

如果您只是尝试生成没有任何安全属性的唯一ID,请使用现有的生成算法(例如UUID)。

在紧要关头,您可以根据PID +当前时间+每个进程序列号轻松生成此类ID:

  • PID在一段时间内是唯一的,通常是几小时(虽然可能在重新启动机器或pid_max较低时可能更少)。
  • 至少具有第二分辨率的PID +时间应该是机器存在时的唯一过程标识符(忽略时区恶作剧)。
  • 如果在一秒钟内请求多个ID,请避免分配相同的ID,请添加每个进程的计数器。

请注意,此类ID是可预测的,不应用于指定安全敏感数据。应用哈希函数不会添加任何保护,但可以方便地将ID列入固定宽度。当这些ID在多台计算机上必须是唯一的时,这些ID是不合适的。

如果您只是尝试生成临时文件,请使用现有模块,例如File::Temp