【问题标题】:Is using a GUID a valid way to generate a random string of characters and numbers? [duplicate]使用 GUID 是生成随机字符串和数字的有效方法吗? [复制]
【发布时间】:2010-10-29 09:24:15
【问题描述】:

可能重复:
How Random is System.Guid.NewGuid()?

基于this question我想知道使用GUID生成随机字符串和数字是否有任何缺陷?

因此,例如,如果我想要一个随机字符串和 32 个或更少字符的数字,我可以使用以下 C# 代码:

string s = Guid.NewGuid().ToString().Replace("-", "");

如果长度需要小于 32,我会截断字符串,如果需要更长,我会添加多个 GUID。

这种方法有什么缺陷?

写完这篇文章后,我意识到一个缺陷是它只会有字母 a 到 f,所以我将修改问题:

这是一个真正的 6 个字符和 10 个数字的随机序列吗?

【问题讨论】:

  • 你能描述一下你想要随机字符的目的吗?
  • 我正在考虑将其用于电子邮件验证令牌。即,用户在网站上注册,并向用户发送一封确认电子邮件,其中包含 32 个字符的令牌作为验证 URL 的参数。

标签: c# .net random


【解决方案1】:

GUID 不保证随机性,它保证唯一性。如果你想要随机性,请使用 Random 生成一个字符串。

【讨论】:

【解决方案2】:

它实际上并不是随机的,而是(相对)独特的。如果你真的想要随机性,我建议使用 System.Random 中值的哈希值。

Here's .NET "System.Random" 的 MSDN 文档的链接,以及他们的 Hashing package 的链接。

【讨论】:

    【解决方案3】:

    正如其他答案所解释的,GUID 只保证唯一性,而不是随机性。

    如果您只需要唯一性,那么您问题中的代码就可以了,尽管您可以只使用 Guid.NewGuid().ToString("N") 而不是显式替换连字符。

    如果您确实需要随机字符串,请尝试以下操作:

    // use RNGCryptoServiceProvider instead of Random if you need extra security
    private readonly Random _rng = new Random();
    
    public string GetRandomString(int length)
    {
        const string allowedChars =
            "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    
        char[] buffer = new char[length];
    
        for (int i = 0; i < length; i++)
        {
            buffer[i] = allowedChars[_rng.Next(allowedChars.Length)];
        }
    
        return new string(buffer);
    }
    

    【讨论】:

      【解决方案4】:

      没有。例如,标准的 GUID 生成算法包括当前时间和生成计算机的 MAC 地址。

      【讨论】:

        【解决方案5】:

        如前所述,GUID 被设计为唯一的而不是随机的。生成"random" string(即满足某些随机性统计要求)的更好且相当简单的方法是使用Random

        /// <summary>
        /// Generates a random string with the given length
        /// </summary>
        /// <param name="size">Size of the string</param>
        /// <param name="lowerCase">If true, generate lowercase string</param>
        /// <returns>Random string</returns>
        private string RandomString(int size, bool lowerCase)
        {
            StringBuilder builder = new StringBuilder();
            Random random = new Random();
            char ch;
            for (int i = 0; i < size; i++)
            {
                ch = Convert.ToChar(Convert.ToInt32(Math.Floor(26 * random.NextDouble() + 65)));
                builder.Append(ch);
            }
            if (lowerCase)
                return builder.ToString().ToLower();
            return builder.ToString();
        }
        

        如果您需要“更安全”的随机数,您可能需要查看RNGCryptoServiceProvider。但正如 John von Neumann said:

        任何考虑产生随机数字的算术方法的人当然都处于罪恶状态。

        【讨论】:

          【解决方案6】:

          如前所述,GUID 旨在生成唯一的,然后几乎保持静态。由于所有随机生成都只是伪随机(在生成几千个整数值后您将开始看到模式),因此最好使用标准的 Random() 类。每次它构造一个新对象时,它都会用当前系统时间播种它。这将保证它最接近随机。你永远不应该使用静态的东西来播种 Random 方法。

          【讨论】:

            【解决方案7】:

            由于 Guid 是唯一的,因此解决方案是可以的。

            【讨论】:

            • OP 正在寻找一个随机字符串,而不是一个简单的唯一字符串。由于 GUID 只保证唯一性,而不是随机性,因此解决方案不正确。
            • 唯一并不意味着不可猜测 - 虽然我不知道有任何关于“按顺序猜测下一个 UUID”的工作,但据我所知,它不是 UUID 算法的设计属性,所以我会鼓励使用实际的 (P?)RNG。
            • 唯一性不保证随机性。前任。 (staticcount++) 对于每个返回值都可以认为是唯一的,但绝对不是随机的 {1,2,3,4,5...}
            • OP 还提到将 GUID 字符串截断为所需的长度 - 如果他们这样做,它就不太可能是唯一的。
            猜你喜欢
            • 2012-12-29
            • 1970-01-01
            • 2011-09-23
            • 2010-11-01
            • 2020-12-01
            • 2013-06-07
            • 1970-01-01
            • 2018-01-06
            • 2010-12-07
            相关资源
            最近更新 更多