简体   繁体   English

如何生成随机字母数字字符串?

[英]How can I generate random alphanumeric strings?

How can I generate a random 8 character alphanumeric string in C#?如何在 C# 中生成随机的 8 个字符的字母数字字符串?

I heard LINQ is the new black, so here's my attempt using LINQ:我听说 LINQ 是新的黑色,所以这是我使用 LINQ 的尝试:

private static Random random = new Random();

public static string RandomString(int length)
{
    const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    return new string(Enumerable.Repeat(chars, length)
        .Select(s => s[random.Next(s.Length)]).ToArray());
}

(Note: The use of the Random class makes this unsuitable for anything security related , such as creating passwords or tokens. Use the RNGCryptoServiceProvider class if you need a strong random number generator.) (注意:使用Random类使其不适用于任何与安全相关的事情,例如创建密码或令牌。如果您需要强大的随机数生成器,请使用RNGCryptoServiceProvider类。)

var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var stringChars = new char[8];
var random = new Random();

for (int i = 0; i < stringChars.Length; i++)
{
    stringChars[i] = chars[random.Next(chars.Length)];
}

var finalString = new String(stringChars);

Not as elegant as the Linq solution.不如 Linq 解决方案优雅。

(Note: The use of the Random class makes this unsuitable for anything security related , such as creating passwords or tokens. Use the RNGCryptoServiceProvider class if you need a strong random number generator.) (注意:使用Random类使其不适用于任何与安全相关的事情,例如创建密码或令牌。如果您需要强大的随机数生成器,请使用RNGCryptoServiceProvider类。)

UPDATED for .NET 6. RNGCryptoServiceProvider is marked as obsolete.已针对 .NET 6 更新。RNGCryptoServiceProvider 被标记为已过时。 Instead, call RandomNumberGenerator.Create() .相反,请调用RandomNumberGenerator.Create() The code in the answer has been updated accordingly.答案中的代码已相应更新。

UPDATED based on comments.根据评论更新。 The original implementation generated ah ~1.95% of the time and the remaining characters ~1.56% of the time.原始实现生成 ah ~1.95% 的时间,剩余的字符 ~1.56% 的时间。 The update generates all characters ~1.61% of the time.更新生成所有字符的概率约为 1.61%。

FRAMEWORK SUPPORT - .NET Core 3 (and future platforms that support .NET Standard 2.1 or above) provides a cryptographically sound method RandomNumberGenerator.GetInt32() to generate a random integer within a desired range.框架支持 - .NET Core 3(以及支持 .NET Standard 2.1 或更高版本的未来平台)提供了一种加密健全的方法RandomNumberGenerator.GetInt32()来生成所需范围内的随机整数。

Unlike some of the alternatives presented, this one is cryptographically sound .与提出的一些替代方案不同,这个方案在密码学上是可靠的。

using System;
using System.Security.Cryptography;
using System.Text;

namespace UniqueKey
{
    public class KeyGenerator
    {
        internal static readonly char[] chars =
            "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray(); 

        public static string GetUniqueKey(int size)
        {            
            byte[] data = new byte[4*size];
            using (var crypto = RandomNumberGenerator.Create())
            {
                crypto.GetBytes(data);
            }
            StringBuilder result = new StringBuilder(size);
            for (int i = 0; i < size; i++)
            {
                var rnd = BitConverter.ToUInt32(data, i * 4);
                var idx = rnd % chars.Length;

                result.Append(chars[idx]);
            }

            return result.ToString();
        }

        public static string GetUniqueKeyOriginal_BIASED(int size)
        {
            char[] chars =
                "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
            byte[] data = new byte[size];
            using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
            {
                crypto.GetBytes(data);
            }
            StringBuilder result = new StringBuilder(size);
            foreach (byte b in data)
            {
                result.Append(chars[b % (chars.Length)]);
            }
            return result.ToString();
        }
    }
}

Based on a discussion of alternatives here and updated/modified based on the comments below.基于此处对替代方案的讨论,并根据以下评论进行更新/修改。

Here's a small test harness that demonstrates the distribution of characters in the old and updated output.这是一个小型测试工具,演示了旧输出和更新输出中的字符分布。 For a deep discussion of the analysis of randomness , check out random.org.有关随机性分析的深入讨论,请查看 random.org。

using System;
using System.Collections.Generic;
using System.Linq;
using UniqueKey;

namespace CryptoRNGDemo
{
    class Program
    {

        const int REPETITIONS = 1000000;
        const int KEY_SIZE = 32;

        static void Main(string[] args)
        {
            Console.WriteLine("Original BIASED implementation");
            PerformTest(REPETITIONS, KEY_SIZE, KeyGenerator.GetUniqueKeyOriginal_BIASED);

            Console.WriteLine("Updated implementation");
            PerformTest(REPETITIONS, KEY_SIZE, KeyGenerator.GetUniqueKey);
            Console.ReadKey();
        }

        static void PerformTest(int repetitions, int keySize, Func<int, string> generator)
        {
            Dictionary<char, int> counts = new Dictionary<char, int>();
            foreach (var ch in UniqueKey.KeyGenerator.chars) counts.Add(ch, 0);

            for (int i = 0; i < REPETITIONS; i++)
            {
                var key = generator(KEY_SIZE); 
                foreach (var ch in key) counts[ch]++;
            }

            int totalChars = counts.Values.Sum();
            foreach (var ch in UniqueKey.KeyGenerator.chars)
            {
                Console.WriteLine($"{ch}: {(100.0 * counts[ch] / totalChars).ToString("#.000")}%");
            }
        }
    }
}

Solution 1 - largest 'range' with most flexible length解决方案 1 - 具有最灵活长度的最大“范围”

string get_unique_string(int string_length) {
    using(var rng = new RNGCryptoServiceProvider()) {
        var bit_count = (string_length * 6);
        var byte_count = ((bit_count + 7) / 8); // rounded up
        var bytes = new byte[byte_count];
        rng.GetBytes(bytes);
        return Convert.ToBase64String(bytes);
    }
}

This solution has more range than using a GUID because a GUID has a couple of fixed bits that are always the same and therefore not random, for example the 13 character in hex is always "4" - at least in a version 6 GUID.此解决方案比使用 GUID 具有更大的范围,因为 GUID 具有几个始终相同且因此不是随机的固定位,例如十六进制中的 13 个字符始终为“4” - 至少在版本 6 GUID 中。

This solution also lets you generate a string of any length.此解决方案还允许您生成任意长度的字符串。

Solution 2 - One line of code - good for up to 22 characters解决方案 2 - 一行代码 - 适用于最多 22 个字符

Convert.ToBase64String(Guid.NewGuid().ToByteArray()).Substring(0, 8);

You can't generate strings as long as Solution 1 and the string doesn't have the same range due to fixed bits in GUID's, but in a lot of cases this will do the job.只要解决方案 1和字符串由于 GUID 中的固定位而具有不同的范围,您就无法生成字符串,但在很多情况下,这将完成这项工作。

Solution 3 - Slightly less code解决方案 3 - 稍微少一点的代码

Guid.NewGuid().ToString("n").Substring(0, 8);

Mostly keeping this here for historical purpose.主要出于历史目的将其保留在这里。 It uses slightly less code, that though comes as the expense of having less range - because it uses hex instead of base64 it takes more characters to represent the same range compared the other solutions.它使用的代码略少,尽管以减少范围为代价 - 因为它使用十六进制而不是 base64,与其他解决方案相比,它需要更多的字符来表示相同的范围。

Which means more chance of collision - testing it with 100,000 iterations of 8 character strings generated one duplicate.这意味着更多的碰撞机会 - 用 8 个字符串的 100,000 次迭代测试它会生成一个重复项。

Here's an example that I stole from Sam Allen example at Dot Net Perls这是我从Dot Net Perls的 Sam Allen 示例中窃取的示例

If you only need 8 characters, then use Path.GetRandomFileName() in the System.IO namespace.如果您只需要 8 个字符,则在 System.IO 命名空间中使用 Path.GetRandomFileName()。 Sam says using the "Path.GetRandomFileName method here is sometimes superior, because it uses RNGCryptoServiceProvider for better randomness. However, it is limited to 11 random characters." Sam 说“这里使用 Path.GetRandomFileName 方法有时会更好,因为它使用 RNGCryptoServiceProvider 以获得更好的随机性。但是,它仅限于 11 个随机字符。”

GetRandomFileName always returns a 12 character string with a period at the 9th character. GetRandomFileName 总是返回一个 12 个字符的字符串,在第 9 个字符处带有句点。 So you'll need to strip the period (since that's not random) and then take 8 characters from the string.因此,您需要去掉句点(因为这不是随机的),然后从字符串中取出 8 个字符。 Actually, you could just take the first 8 characters and not worry about the period.实际上,您可以只取前 8 个字符而不必担心句号。

public string Get8CharacterRandomString()
{
    string path = Path.GetRandomFileName();
    path = path.Replace(".", ""); // Remove period.
    return path.Substring(0, 8);  // Return 8 character string
}

PS: thanks Sam PS:谢谢山姆

The main goals of my code are:我的代码的主要目标是:

  1. The distribution of strings is almost uniform (don't care about minor deviations, as long as they're small)字符串的分布几乎是均匀的(不关心微小的偏差,只要它们很小)
  2. It outputs more than a few billion strings for each argument set.它为每个参数集输出超过几十亿个字符串。 Generating an 8 character string (~47 bits of entropy) is meaningless if your PRNG only generates 2 billion (31 bits of entropy) different values.如果您的 PRNG 只生成 20 亿(31 位熵)不同的值,那么生成 8 个字符串(约 47 位熵)是没有意义的。
  3. It's secure, since I expect people to use this for passwords or other security tokens.它是安全的,因为我希望人们将它用于密码或其他安全令牌。

The first property is achieved by taking a 64 bit value modulo the alphabet size.第一个属性是通过以字母大小为模取一个 64 位值来实现的。 For small alphabets (such as the 62 characters from the question) this leads to negligible bias.对于小字母(例如问题中的 62 个字符),这会导致可忽略的偏差。 The second and third property are achieved by using RNGCryptoServiceProvider instead of System.Random .第二个和第三个属性是通过使用RNGCryptoServiceProvider而不是System.Random来实现的。

using System;
using System.Security.Cryptography;

public static string GetRandomAlphanumericString(int length)
{
    const string alphanumericCharacters =
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
        "abcdefghijklmnopqrstuvwxyz" +
        "0123456789";
    return GetRandomString(length, alphanumericCharacters);
}

public static string GetRandomString(int length, IEnumerable<char> characterSet)
{
    if (length < 0)
        throw new ArgumentException("length must not be negative", "length");
    if (length > int.MaxValue / 8) // 250 million chars ought to be enough for anybody
        throw new ArgumentException("length is too big", "length");
    if (characterSet == null)
        throw new ArgumentNullException("characterSet");
    var characterArray = characterSet.Distinct().ToArray();
    if (characterArray.Length == 0)
        throw new ArgumentException("characterSet must not be empty", "characterSet");

    var bytes = new byte[length * 8];
    var result = new char[length];
    using (var cryptoProvider = new RNGCryptoServiceProvider())
    {
        cryptoProvider.GetBytes(bytes);
    }
    for (int i = 0; i < length; i++)
    {
        ulong value = BitConverter.ToUInt64(bytes, i * 8);
        result[i] = characterArray[value % (uint)characterArray.Length];
    }
    return new string(result);
}

The simplest:最简单的:

public static string GetRandomAlphaNumeric()
{
    return Path.GetRandomFileName().Replace(".", "").Substring(0, 8);
}

You can get better performance if you hard code the char array and rely on System.Random :如果您对 char 数组进行硬编码并依赖System.Random ,您可以获得更好的性能:

public static string GetRandomAlphaNumeric()
{
    var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
    return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray());
}

If ever you worry the English alphabets can change sometime around and you might lose business, then you can avoid hard coding, but should perform slightly worse (comparable to Path.GetRandomFileName approach)如果您担心英文字母可能会在某个时候发生变化并且您可能会失去业务,那么您可以避免硬编码,但性能应该稍差(与Path.GetRandomFileName方法相比)

public static string GetRandomAlphaNumeric()
{
    var chars = 'a'.To('z').Concat('0'.To('9')).ToList();
    return new string(chars.Select(c => chars[random.Next(chars.Length)]).Take(8).ToArray());
}

public static IEnumerable<char> To(this char start, char end)
{
    if (end < start)
        throw new ArgumentOutOfRangeException("the end char should not be less than start char", innerException: null);
    return Enumerable.Range(start, end - start + 1).Select(i => (char)i);
}

The last two approaches looks better if you can make them an extension method on System.Random instance.如果您可以将最后两种方法作为System.Random实例的扩展方法,则它们看起来会更好。

Just some performance comparisons of the various answers in this thread:只是这个线程中各种答案的一些性能比较:

Methods & Setup方法和设置

// what's available
public static string possibleChars = "abcdefghijklmnopqrstuvwxyz";
// optimized (?) what's available
public static char[] possibleCharsArray = possibleChars.ToCharArray();
// optimized (precalculated) count
public static int possibleCharsAvailable = possibleChars.Length;
// shared randomization thingy
public static Random random = new Random();


// http://stackoverflow.com/a/1344242/1037948
public string LinqIsTheNewBlack(int num) {
    return new string(
    Enumerable.Repeat(possibleCharsArray, num)
              .Select(s => s[random.Next(s.Length)])
              .ToArray());
}

// http://stackoverflow.com/a/1344258/1037948
public string ForLoop(int num) {
    var result = new char[num];
    while(num-- > 0) {
        result[num] = possibleCharsArray[random.Next(possibleCharsAvailable)];
    }
    return new string(result);
}

public string ForLoopNonOptimized(int num) {
    var result = new char[num];
    while(num-- > 0) {
        result[num] = possibleChars[random.Next(possibleChars.Length)];
    }
    return new string(result);
}

public string Repeat(int num) {
    return new string(new char[num].Select(o => possibleCharsArray[random.Next(possibleCharsAvailable)]).ToArray());
}

// http://stackoverflow.com/a/1518495/1037948
public string GenerateRandomString(int num) {
  var rBytes = new byte[num];
  random.NextBytes(rBytes);
  var rName = new char[num];
  while(num-- > 0)
    rName[num] = possibleCharsArray[rBytes[num] % possibleCharsAvailable];
  return new string(rName);
}

//SecureFastRandom - or SolidSwiftRandom
static string GenerateRandomString(int Length) //Configurable output string length
{
    byte[] rBytes = new byte[Length]; 
    char[] rName = new char[Length];
    SolidSwiftRandom.GetNextBytesWithMax(rBytes, biasZone);
    for (var i = 0; i < Length; i++)
    {
        rName[i] = charSet[rBytes[i] % charSet.Length];
    }
    return new string(rName);
}

Results结果

Tested in LinqPad.在 LinqPad 中测试。 For string size of 10, generates:对于 10 的字符串大小,生成:

  • from Linq = chdgmevhcy [10]来自 Linq = chdgmevhcy [10]
  • from Loop = gtnoaryhxr [10]从循环 = gtnoaryhxr [10]
  • from Select = rsndbztyby [10]从选择 = rsndbztyby [10]
  • from GenerateRandomString = owyefjjakj [10]从 GenerateRandomString = owyefjjakj [10]
  • from SecureFastRandom = VzougLYHYP [10]来自 SecureFastRandom = VzougLYHYP [10]
  • from SecureFastRandom-NoCache = oVQXNGmO1S [10]从 SecureFastRandom-NoCache = oVQXNGmO1S [10]

And the performance numbers tend to vary slightly, very occasionally NonOptimized is actually faster, and sometimes ForLoop and GenerateRandomString switch who's in the lead.并且性能数字往往略有不同,偶尔NonOptimized实际上更快,有时ForLoopGenerateRandomString切换谁处于领先地位。

  • LinqIsTheNewBlack (10000x) = 96762 ticks elapsed (9.6762 ms) LinqIsTheNewBlack (10000x) = 96762 滴答经过 (9.6762 毫秒)
  • ForLoop (10000x) = 28970 ticks elapsed (2.897 ms) ForLoop (10000x) = 28970 个滴答经过(2.897 毫秒)
  • ForLoopNonOptimized (10000x) = 33336 ticks elapsed (3.3336 ms) ForLoopNonOptimized (10000x) = 经过 33336 个刻度(3.3336 毫秒)
  • Repeat (10000x) = 78547 ticks elapsed (7.8547 ms)重复 (10000x) = 78547 滴答经过(7.8547 毫秒)
  • GenerateRandomString (10000x) = 27416 ticks elapsed (2.7416 ms) GenerateRandomString (10000x) = 27416 个滴答经过 (2.7416 ms)
  • SecureFastRandom (10000x) = 13176 ticks elapsed (5ms) lowest [Different machine] SecureFastRandom (10000x) = 13176 ticks elapsed (5ms) 最低 [不同机器]
  • SecureFastRandom-NoCache (10000x) = 39541 ticks elapsed (17ms) lowest [Different machine] SecureFastRandom-NoCache (10000x) = 39541 ticks elapsed (17ms) 最低 [不同机器]

One line of code Membership.GeneratePassword() does the trick :)一行代码Membership.GeneratePassword()就可以了:)

Here is a demo for the same.这是相同的演示

The code written by Eric J. is quite sloppy (it is quite clear that it is from 6 years ago... he probably wouldn't write that code today), and there are even some problems. Eric J.写的代码很草率(很明显是6年前的……他今天可能不会写那个代码),甚至还有一些问题。

Unlike some of the alternatives presented, this one is cryptographically sound.与提出的一些替代方案不同,这个方案在密码学上是可靠的。

Untrue... There is a bias in the password (as written in a comment), bcdefgh are a little more probable than the others (the a isn't because by the GetNonZeroBytes it isn't generating bytes with a value of zero, so the bias for the a is balanced by it), so it isn't really cryptographically sound.不真实...密码存在偏差(如评论中所写), bcdefgh比其他密码更可能( a不是因为GetNonZeroBytes不会生成值为零的字节,所以a的偏差被它平衡了),所以它在密码学上并不是真正的健全的。

This should correct all the problems.这应该可以解决所有问题。

public static string GetUniqueKey(int size = 6, string chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
{
    using (var crypto = new RNGCryptoServiceProvider())
    {
        var data = new byte[size];

        // If chars.Length isn't a power of 2 then there is a bias if
        // we simply use the modulus operator. The first characters of
        // chars will be more probable than the last ones.

        // buffer used if we encounter an unusable random byte. We will
        // regenerate it in this buffer
        byte[] smallBuffer = null;

        // Maximum random number that can be used without introducing a
        // bias
        int maxRandom = byte.MaxValue - ((byte.MaxValue + 1) % chars.Length);

        crypto.GetBytes(data);

        var result = new char[size];

        for (int i = 0; i < size; i++)
        {
            byte v = data[i];

            while (v > maxRandom)
            {
                if (smallBuffer == null)
                {
                    smallBuffer = new byte[1];
                }

                crypto.GetBytes(smallBuffer);
                v = smallBuffer[0];
            }

            result[i] = chars[v % chars.Length];
        }

        return new string(result);
    }
}

My simple one line code works for me :)我简单的一行代码对我有用:)

string  random = string.Join("", Guid.NewGuid().ToString("n").Take(8).Select(o => o));

Response.Write(random.ToUpper());
Response.Write(random.ToLower());

To expand on this for any length string扩展任何长度的字符串

    public static string RandomString(int length)
    {
        //length = length < 0 ? length * -1 : length;
        var str = "";

        do 
        {
            str += Guid.NewGuid().ToString().Replace("-", "");
        }

        while (length > str.Length);

        return str.Substring(0, length);
    }

We also use custom string random but we implemented is as a string's helper so it provides some flexibility...我们还使用自定义字符串随机,但我们实现的是作为字符串的助手,因此它提供了一些灵活性......

public static string Random(this string chars, int length = 8)
{
    var randomString = new StringBuilder();
    var random = new Random();

    for (int i = 0; i < length; i++)
        randomString.Append(chars[random.Next(chars.Length)]);

    return randomString.ToString();
}

Usage用法

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".Random();

or或者

var random = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789".Random(16);
 public static string RandomString(int length)
    {
        const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
        var random = new Random();
        return new string(Enumerable.Repeat(chars, length).Select(s => s[random.Next(s.Length)]).ToArray());
    }

After reviewing the other answers and considering CodeInChaos' comments, along with CodeInChaos still biased (although less) answer, I thought a final ultimate cut and paste solution was needed.在查看了其他答案并考虑了 CodeInChaos 的评论以及 CodeInChaos 仍然有偏见(尽管较少)的答案之后,我认为需要最终的最终剪切和粘贴解决方案 So while updating my answer I decided to go all out.因此,在更新我的答案时,我决定全力以赴。

For an up to date version of this code, please visit the new Hg repository on Bitbucket: https://bitbucket.org/merarischroeder/secureswiftrandom .有关此代码的最新版本,请访问 Bitbucket 上的新 Hg 存储库: https ://bitbucket.org/merarischroeder/secureswiftrandom。 I recommend you copy and paste the code from: https://bitbucket.org/merarischroeder/secureswiftrandom/src/6c14b874f34a3f6576b0213379ecdf0ffc7496ea/Code/Alivate.SolidSwiftRandom/SolidSwiftRandom.cs?at=default&fileviewer=file-view-default (make sure you click the Raw button to make it easier to copy and make sure you have the latest version, I think this link goes to a specific version of the code, not the latest).我建议您从以下位置复制并粘贴代码: https ://bitbucket.org/merarischroeder/secureswiftrandom/src/6c14b874f34a3f6576b0213379ecdf0ffc7496ea/Code/Alivate.SolidSwiftRandom/SolidSwiftRandom.cs?at=default&fileviewer=file-view-default(确保单击Raw 按钮可以更轻松地复制并确保您拥有最新版本,我认为此链接指向代码的特定版本,而不是最新版本)。

Updated notes:更新说明:

  1. Relating to some other answers - If you know the length of the output, you don't need a StringBuilder, and when using ToCharArray, this creates and fills the array (you don't need to create an empty array first)与其他一些答案有关 - 如果您知道输出的长度,则不需要 StringBuilder,并且在使用 ToCharArray 时,这会创建并填充数组(您不需要先创建空数组)
  2. Relating to some other answers - You should use NextBytes, rather than getting one at a time for performance与其他一些答案有关-您应该使用 NextBytes,而不是一次获得一个以提高性能
  3. Technically you could pin the byte array for faster access.. it's usually worth it when your iterating more than 6-8 times over a byte array.从技术上讲,您可以固定字节数组以获得更快的访问速度。当您在字节数组上迭代超过 6-8 次时,这通常是值得的。 (Not done here) (这里没有做)
  4. Use of RNGCryptoServiceProvider for best randomness使用RNGCryptoServiceProvider 获得最佳随机性
  5. Use of caching of a 1MB buffer of random data - benchmarking shows cached single bytes access speed is ~1000x faster - taking 9ms over 1MB vs 989ms for uncached.使用1MB 随机数据缓冲区的缓存- 基准测试显示缓存的单字节访问速度快了约 1000 倍 - 1MB 需要 9 毫秒,而未缓存则需要 989 毫秒。
  6. Optimised rejection of bias zone within my new class.在我的新班级中优化了对偏见区域的拒绝

End solution to question:结束问题的解决方案:

static char[] charSet =  "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();
static int byteSize = 256; //Labelling convenience
static int biasZone = byteSize - (byteSize % charSet.Length);
public string GenerateRandomString(int Length) //Configurable output string length
{
    byte[] rBytes = new byte[Length]; //Do as much before and after lock as possible
    char[] rName = new char[Length];
    SecureFastRandom.GetNextBytesMax(rBytes, biasZone);
    for (var i = 0; i < Length; i++)
    {
        rName[i] = charSet[rBytes[i] % charSet.Length];
    }
    return new string(rName);
}

But you need my new (untested) class:但是您需要我的新(未经测试)课程:

/// <summary>
/// My benchmarking showed that for RNGCryptoServiceProvider:
/// 1. There is negligable benefit of sharing RNGCryptoServiceProvider object reference 
/// 2. Initial GetBytes takes 2ms, and an initial read of 1MB takes 3ms (starting to rise, but still negligable)
/// 2. Cached is ~1000x faster for single byte at a time - taking 9ms over 1MB vs 989ms for uncached
/// </summary>
class SecureFastRandom
{
    static byte[] byteCache = new byte[1000000]; //My benchmark showed that an initial read takes 2ms, and an initial read of this size takes 3ms (starting to raise)
    static int lastPosition = 0;
    static int remaining = 0;

    /// <summary>
    /// Static direct uncached access to the RNGCryptoServiceProvider GetBytes function
    /// </summary>
    /// <param name="buffer"></param>
    public static void DirectGetBytes(byte[] buffer)
    {
        using (var r = new RNGCryptoServiceProvider())
        {
            r.GetBytes(buffer);
        }
    }

    /// <summary>
    /// Main expected method to be called by user. Underlying random data is cached from RNGCryptoServiceProvider for best performance
    /// </summary>
    /// <param name="buffer"></param>
    public static void GetBytes(byte[] buffer)
    {
        if (buffer.Length > byteCache.Length)
        {
            DirectGetBytes(buffer);
            return;
        }

        lock (byteCache)
        {
            if (buffer.Length > remaining)
            {
                DirectGetBytes(byteCache);
                lastPosition = 0;
                remaining = byteCache.Length;
            }

            Buffer.BlockCopy(byteCache, lastPosition, buffer, 0, buffer.Length);
            lastPosition += buffer.Length;
            remaining -= buffer.Length;
        }
    }

    /// <summary>
    /// Return a single byte from the cache of random data.
    /// </summary>
    /// <returns></returns>
    public static byte GetByte()
    {
        lock (byteCache)
        {
            return UnsafeGetByte();
        }
    }

    /// <summary>
    /// Shared with public GetByte and GetBytesWithMax, and not locked to reduce lock/unlocking in loops. Must be called within lock of byteCache.
    /// </summary>
    /// <returns></returns>
    static byte UnsafeGetByte()
    {
        if (1 > remaining)
        {
            DirectGetBytes(byteCache);
            lastPosition = 0;
            remaining = byteCache.Length;
        }

        lastPosition++;
        remaining--;
        return byteCache[lastPosition - 1];
    }

    /// <summary>
    /// Rejects bytes which are equal to or greater than max. This is useful for ensuring there is no bias when you are modulating with a non power of 2 number.
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="max"></param>
    public static void GetBytesWithMax(byte[] buffer, byte max)
    {
        if (buffer.Length > byteCache.Length / 2) //No point caching for larger sizes
        {
            DirectGetBytes(buffer);

            lock (byteCache)
            {
                UnsafeCheckBytesMax(buffer, max);
            }
        }
        else
        {
            lock (byteCache)
            {
                if (buffer.Length > remaining) //Recache if not enough remaining, discarding remaining - too much work to join two blocks
                    DirectGetBytes(byteCache);

                Buffer.BlockCopy(byteCache, lastPosition, buffer, 0, buffer.Length);
                lastPosition += buffer.Length;
                remaining -= buffer.Length;

                UnsafeCheckBytesMax(buffer, max);
            }
        }
    }

    /// <summary>
    /// Checks buffer for bytes equal and above max. Must be called within lock of byteCache.
    /// </summary>
    /// <param name="buffer"></param>
    /// <param name="max"></param>
    static void UnsafeCheckBytesMax(byte[] buffer, byte max)
    {
        for (int i = 0; i < buffer.Length; i++)
        {
            while (buffer[i] >= max)
                buffer[i] = UnsafeGetByte(); //Replace all bytes which are equal or above max
        }
    }
}

For history - my older solution for this answer, used Random object:对于历史-我对此答案的旧解决方案使用了 Random 对象:

    private static char[] charSet =
      "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".ToCharArray();

    static rGen = new Random(); //Must share, because the clock seed only has Ticks (~10ms) resolution, yet lock has only 20-50ns delay.
    static int byteSize = 256; //Labelling convenience
    static int biasZone = byteSize - (byteSize % charSet.Length);
    static bool SlightlyMoreSecurityNeeded = true; //Configuration - needs to be true, if more security is desired and if charSet.Length is not divisible by 2^X.
    public string GenerateRandomString(int Length) //Configurable output string length
    {
      byte[] rBytes = new byte[Length]; //Do as much before and after lock as possible
      char[] rName = new char[Length];
      lock (rGen) //~20-50ns
      {
          rGen.NextBytes(rBytes);

          for (int i = 0; i < Length; i++)
          {
              while (SlightlyMoreSecurityNeeded && rBytes[i] >= biasZone) //Secure against 1/5 increased bias of index[0-7] values against others. Note: Must exclude where it == biasZone (that is >=), otherwise there's still a bias on index 0.
                  rBytes[i] = rGen.NextByte();
              rName[i] = charSet[rBytes[i] % charSet.Length];
          }
      }
      return new string(rName);
    }

Performance:表现:

  1. SecureFastRandom - First single run = ~9-33ms . SecureFastRandom -第一次单次运行= ~9-33ms Imperceptible.难以察觉。 Ongoing : 5ms (sometimes it goes up to 13ms) over 10,000 iterations, With a single average iteration= 1.5 microseconds.进行中:超过 10,000 次迭代 5毫秒(有时达到 13 毫秒),单次平均迭代 = 1.5 微秒。 . . Note: Requires generally 2, but occasionally up to 8 cache refreshes - depends on how many single bytes exceed the bias zone注意:通常需要 2 次,但偶尔最多需要 8 次缓存刷新 - 取决于有多少单个字节超出了偏置区域
  2. Random - First single run = ~0-1ms .随机-第一次单次运行= ~0-1ms Imperceptible.难以察觉。 Ongoing : 5ms over 10,000 iterations.进行中:超过 10,000 次迭代5 毫秒 With a single average iteration= .5 microseconds.单次平均迭代 = 0.5 微秒。 . . About the same speed.速度差不多。

Also check out:另请查看:

These links are another approach.这些链接是另一种方法。 Buffering could be added to this new code base, but most important was exploring different approaches to removing bias, and benchmarking the speeds and pros/cons.缓冲可以添加到这个新的代码库中,但最重要的是探索不同的方法来消除偏差,并对速度和优缺点进行基准测试。

Question: Why should I waste my time using Enumerable.Range instead of typing in "ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789" ?问题:为什么我要浪费时间使用Enumerable.Range而不是输入"ABCDEFGHJKLMNOPQRSTUVWXYZ0123456789"

using System;
using System.Collections.Generic;
using System.Linq;

public class Test
{
    public static void Main()
    {
        var randomCharacters = GetRandomCharacters(8, true);
        Console.WriteLine(new string(randomCharacters.ToArray()));
    }

    private static List<char> getAvailableRandomCharacters(bool includeLowerCase)
    {
        var integers = Enumerable.Empty<int>();
        integers = integers.Concat(Enumerable.Range('A', 26));
        integers = integers.Concat(Enumerable.Range('0', 10));

        if ( includeLowerCase )
            integers = integers.Concat(Enumerable.Range('a', 26));

        return integers.Select(i => (char)i).ToList();
    }

    public static IEnumerable<char> GetRandomCharacters(int count, bool includeLowerCase)
    {
        var characters = getAvailableRandomCharacters(includeLowerCase);
        var random = new Random();
        var result = Enumerable.Range(0, count)
            .Select(_ => characters[random.Next(characters.Count)]);

        return result;
    }
}

Answer: Magic strings are BAD.答:魔术弦不好。 Did ANYONE notice there was no " I " in my string at the top?有没有人注意到我的字符串顶部没有“ I ”? My mother taught me not to use magic strings for this very reason...因为这个原因,我妈妈教我不要使用魔线……

nb 1: As many others like @dtb said, don't use System.Random if you need cryptographic security... nb 1:正如@dtb 等许多其他人所说,如果您需要加密安全,请不要使用System.Random ......

nb 2: This answer isn't the most efficient or shortest, but I wanted the space to separate the answer from the question. nb 2:这个答案不是最有效或最短的,但我希望空间将答案与问题分开。 The purpose of my answer is more to warn against magic strings than to provide a fancy innovative answer.我回答的目的更多的是警告魔术字符串,而不是提供一个花哨的创新答案。

A slightly cleaner version of DTB's solution. DTB 解决方案的稍微干净的版本。

    var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    var random = new Random();
    var list = Enumerable.Repeat(0, 8).Select(x=>chars[random.Next(chars.Length)]);
    return string.Join("", list);

Your style preferences may vary.您的风格偏好可能会有所不同。

Another option could be to use Linq and aggregate random chars into a stringbuilder.另一种选择可能是使用 Linq 并将随机字符聚合到字符串生成器中。

var chars = "abcdefghijklmnopqrstuvwxyz123456789".ToArray();
string pw = Enumerable.Range(0, passwordLength)
                      .Aggregate(
                          new StringBuilder(),
                          (sb, n) => sb.Append((chars[random.Next(chars.Length)])),
                          sb => sb.ToString());

Try to combine two parts: unique (sequence, counter or date ) and random尝试结合两个部分:唯一(序列、计数器或日期)和随机

public class RandomStringGenerator
{
    public static string Gen()
    {
        return ConvertToBase(DateTime.UtcNow.ToFileTimeUtc()) + GenRandomStrings(5); //keep length fixed at least of one part
    }

    private static string GenRandomStrings(int strLen)
    {
        var result = string.Empty;

        using (var gen = new RNGCryptoServiceProvider())
        {
            var data = new byte[1];

            while (result.Length < strLen)
            {
                gen.GetNonZeroBytes(data);
                int code = data[0];
                if (code > 48 && code < 57 || // 0-9
                    code > 65 && code < 90 || // A-Z
                    code > 97 && code < 122   // a-z
                )
                {
                    result += Convert.ToChar(code);
                }
            }

            return result;
        }
    }

    private static string ConvertToBase(long num, int nbase = 36)
    {
        const string chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; //if you wish to make the algorithm more secure - change order of letter here

        // check if we can convert to another base
        if (nbase < 2 || nbase > chars.Length)
            return null;

        int r;
        var newNumber = string.Empty;

        // in r we have the offset of the char that was converted to the new base
        while (num >= nbase)
        {
            r = (int)(num % nbase);
            newNumber = chars[r] + newNumber;
            num = num / nbase;
        }
        // the last number to convert
        newNumber = chars[(int)num] + newNumber;

        return newNumber;
    }
}

Tests:测试:

    [Test]
    public void Generator_Should_BeUnigue1()
    {
        //Given
        var loop = Enumerable.Range(0, 1000);
        //When
        var str = loop.Select(x=> RandomStringGenerator.Gen());
        //Then
        var distinct = str.Distinct();
        Assert.AreEqual(loop.Count(),distinct.Count()); // Or Assert.IsTrue(distinct.Count() < 0.95 * loop.Count())
    }

I was looking for a more specific answer, where I want to control the format of the random string and came across this post.我一直在寻找更具体的答案,我想控制随机字符串的格式并遇到了这篇文章。 For example: license plates (of cars) have a specific format (per country) and I wanted to created random license plates.例如:车牌(汽车)具有特定格式(每个国家/地区),我想创建随机车牌。
I decided to write my own extension method of Random for this.我决定为此编写自己的 Random 扩展方法。 (this is in order to reuse the same Random object, as you could have doubles in multi-threading scenarios). (这是为了重用相同的 Random 对象,因为您可以在多线程场景中使用双打)。 I created a gist ( https://gist.github.com/SamVanhoutte/808845ca78b9c041e928 ), but will also copy the extension class here:我创建了一个要点( https://gist.github.com/SamVanhoutte/808845ca78b9c041e928 ),但也会在此处复制扩展类:

void Main()
{
    Random rnd = new Random();
    rnd.GetString("1-###-000").Dump();
}

public static class RandomExtensions
{
    public static string GetString(this Random random, string format)
    {
        // Based on http://stackoverflow.com/questions/1344221/how-can-i-generate-random-alphanumeric-strings-in-c
        // Added logic to specify the format of the random string (# will be random string, 0 will be random numeric, other characters remain)
        StringBuilder result = new StringBuilder();
        for(int formatIndex = 0; formatIndex < format.Length ; formatIndex++)
        {
            switch(format.ToUpper()[formatIndex])
            {
                case '0': result.Append(getRandomNumeric(random)); break;
                case '#': result.Append(getRandomCharacter(random)); break;
                default : result.Append(format[formatIndex]); break;
            }
        }
        return result.ToString();
    }

    private static char getRandomCharacter(Random random)
    {
        string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        return chars[random.Next(chars.Length)];
    }

    private static char getRandomNumeric(Random random)
    {
        string nums = "0123456789";
        return nums[random.Next(nums.Length)];
    }
}

Now in one-liner flavour.现在是单线风味。

private string RandomName()
{
        return new string(
            Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZ", 13)
                .Select(s =>
                {
                    var cryptoResult = new byte[4];
                    using (var cryptoProvider = new RNGCryptoServiceProvider())
                        cryptoProvider.GetBytes(cryptoResult);

                    return s[new Random(BitConverter.ToInt32(cryptoResult, 0)).Next(s.Length)];
                })
                .ToArray());
}

For both crypto & noncrypto, efficiently:对于加密和非加密,有效地:

public static string GenerateRandomString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    new Random().GenerateRandomString(length, charset);

public static string GenerateRandomString(this Random random, int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    RandomString(random.NextBytes, length, charset.ToCharArray());

public static string GenerateRandomCryptoString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
{
    using (var crypto = new System.Security.Cryptography.RNGCryptoServiceProvider())
        return crypto.GenerateRandomCryptoString(length, charset);
}

public static string GenerateRandomCryptoString(this RNGCryptoServiceProvider random, int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") => 
    RandomString(random.GetBytes, length, charset.ToCharArray());

private static string RandomString(Action<byte[]> fillRandomBuffer, int length, char[] charset)
{
    if (length < 0)
        throw new ArgumentOutOfRangeException(nameof(length), $"{nameof(length)} must be greater or equal to 0");
    if (charset is null)
        throw new ArgumentNullException(nameof(charset));
    if (charset.Length == 0)
        throw new ArgumentException($"{nameof(charset)} must contain at least 1 character", nameof(charset));

    var maxIdx = charset.Length;
    var chars = new char[length];
    var randomBuffer = new byte[length * 4];
    fillRandomBuffer(randomBuffer);

    for (var i = 0; i < length; i++)
        chars[i] = charset[BitConverter.ToUInt32(randomBuffer, i * 4) % maxIdx];

    return new string(chars);
}

Using generators & LINQ.使用生成器和 LINQ。 Not the fastest option (especially because it doesn't generate all the bytes in one go) but pretty neat & extensible:不是最快的选择(特别是因为它不会一次性生成所有字节)但非常简洁和可扩展:

private static readonly Random _random = new Random();

public static string GenerateRandomString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    new string(_random.GetGenerator().RandomChars(charset.ToCharArray()).Take(length).ToArray());

public static string GenerateRandomCryptoString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890")
{
    using (var crypto = new System.Security.Cryptography.RNGCryptoServiceProvider())
        return new string(crypto.GetGenerator().RandomChars(charset.ToCharArray()).Take(length).ToArray());
}

public static IEnumerable<char> RandomChars(this Func<uint, IEnumerable<uint>> randomGenerator, char[] charset)
{
    if (charset is null)
        throw new ArgumentNullException(nameof(charset));
    if (charset.Length == 0)
        throw new ArgumentException($"{nameof(charset)} must contain at least 1 character", nameof(charset));

    return randomGenerator((uint)charset.Length).Select(r => charset[r]);
}

public static Func<uint, IEnumerable<uint>> GetGenerator(this Random random)
{
    if (random is null)
        throw new ArgumentNullException(nameof(random));

    return GeneratorFunc_Inner;

    IEnumerable<uint> GeneratorFunc_Inner(uint maxValue)
    {
        if (maxValue > int.MaxValue)
            throw new ArgumentOutOfRangeException(nameof(maxValue));

        return Generator_Inner();

        IEnumerable<uint> Generator_Inner()
        {
            var randomBytes = new byte[4];
            while (true)
            {
                random.NextBytes(randomBytes);
                yield return BitConverter.ToUInt32(randomBytes, 0) % maxValue;
            }
        }
    }
}

public static Func<uint, IEnumerable<uint>> GetGenerator(this System.Security.Cryptography.RNGCryptoServiceProvider random)
{
    if (random is null)
        throw new ArgumentNullException(nameof(random));

    return Generator_Inner;

    IEnumerable<uint> Generator_Inner(uint maxValue)
    {
        var randomBytes = new byte[4];
        while (true)
        {
            random.GetBytes(randomBytes);
            yield return BitConverter.ToUInt32(randomBytes, 0) % maxValue;
        }
    }
}

a simpler version using LINQ for only non-crypto strings:仅对非加密字符串使用 LINQ 的更简单版本:

private static readonly Random _random = new Random();

public static string RandomString(int length, string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890") =>
    new string(_random.GenerateChars(charset).Take(length).ToArray()); 

public static IEnumerable<char> GenerateChars(this Random random, string charset)
{
    if (charset is null) throw new ArgumentNullException(nameof(charset));
    if (charset.Length == 0) throw new ArgumentException($"{nameof(charset)} must contain at least 1 character", nameof(charset));

    return random.Generator(charset.Length).Select(r => charset[r]);
}

public static IEnumerable<int> Generator(this Random random, int maxValue)
{
    if (random is null) throw new ArgumentNullException(nameof(random));

    return Generator_Inner();

    IEnumerable<int> Generator_Inner() { while (true) yield return random.Next(maxValue); }
}

Horrible, I know, but I just couldn't help myself:可怕,我知道,但我就是忍不住:


namespace ConsoleApplication2
{
    using System;
    using System.Text.RegularExpressions;

    class Program
    {
        static void Main(string[] args)
        {
            Random adomRng = new Random();
            string rndString = string.Empty;
            char c;

            for (int i = 0; i < 8; i++)
            {
                while (!Regex.IsMatch((c=Convert.ToChar(adomRng.Next(48,128))).ToString(), "[A-Za-z0-9]"));
                rndString += c;
            }

            Console.WriteLine(rndString + Environment.NewLine);
        }
    }
}

A simple and highly secure way might be generating the cryptography Aes key.一种简单且高度安全的方法可能是生成加密Aes密钥。

public static string GenerateRandomString()
{
    using Aes crypto = Aes.Create();
    crypto.GenerateKey();
    return Convert.ToBase64String(crypto.Key);
}

A solution without using Random :不使用Random的解决方案:

var chars = Enumerable.Repeat("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", 8);

var randomStr = new string(chars.SelectMany(str => str)
                                .OrderBy(c => Guid.NewGuid())
                                .Take(8).ToArray());

Here is a variant of Eric J's solution, ie cryptographically sound, for WinRT (Windows Store App):这是 Eric J 解决方案的一个变体,即 WinRT(Windows 应用商店应用程序)的加密声音:

public static string GenerateRandomString(int length)
{
    var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    var result = new StringBuilder(length);
    for (int i = 0; i < length; ++i)
    {
        result.Append(CryptographicBuffer.GenerateRandomNumber() % chars.Length);
    }
    return result.ToString();
}

If performance matters (especially when length is high):如果性能很重要(特别是当长度很长时):

public static string GenerateRandomString(int length)
{
    var chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
    var result = new System.Text.StringBuilder(length);
    var bytes = CryptographicBuffer.GenerateRandom((uint)length * 4).ToArray();
    for (int i = 0; i < bytes.Length; i += 4)
    {
        result.Append(BitConverter.ToUInt32(bytes, i) % chars.Length);
    }
    return result.ToString();
}

I know this one is not the best way.我知道这不是最好的方法。 But you can try this.但是你可以试试这个。

string str = Path.GetRandomFileName(); //This method returns a random file name of 11 characters
str = str.Replace(".","");
Console.WriteLine("Random string: " + str);

I don't know how cryptographically sound this is, but it's more readable and concise than the more intricate solutions by far (imo), and it should be more "random" than System.Random -based solutions.我不知道这在密码学上听起来如何,但它比迄今为止更复杂的解决方案(imo)更具可读性和简洁性,并且它应该比基于System.Random的解决方案更“随机”。

return alphabet
    .OrderBy(c => Guid.NewGuid())
    .Take(strLength)
    .Aggregate(
        new StringBuilder(),
        (builder, c) => builder.Append(c))
    .ToString();

I can't decide if I think this version or the next one is "prettier", but they give the exact same results:我无法决定我认为这个版本还是下一个版本“更漂亮”,但它们给出了完全相同的结果:

return new string(alphabet
    .OrderBy(o => Guid.NewGuid())
    .Take(strLength)
    .ToArray());

Granted, it isn't optimized for speed, so if it's mission critical to generate millions of random strings every second, try another one!当然,它没有针对速度进行优化,所以如果每秒生成数百万个随机字符串是关键任务,请尝试另一个!

NOTE: This solution doesn't allow for repetitions of symbols in the alphabet, and the alphabet MUST be of equal or greater size than the output string, making this approach less desirable in some circumstances, it all depends on your use-case.注意:此解决方案不允许重复字母表中的符号,并且字母表的大小必须等于或大于输出字符串,这使得这种方法在某些情况下不太理想,这完全取决于您的用例。

public static class StringHelper
{
    private static readonly Random random = new Random();

    private const int randomSymbolsDefaultCount = 8;
    private const string availableChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    private static int randomSymbolsIndex = 0;

    public static string GetRandomSymbols()
    {
        return GetRandomSymbols(randomSymbolsDefaultCount);
    }

    public static string GetRandomSymbols(int count)
    {
        var index = randomSymbolsIndex;
        var result = new string(
            Enumerable.Repeat(availableChars, count)
                      .Select(s => {
                          index += random.Next(s.Length);
                          if (index >= s.Length)
                              index -= s.Length;
                          return s[index];
                      })
                      .ToArray());
        randomSymbolsIndex = index;
        return result;
    }
}

If your values are not completely random, but in fact may depend on something - you may compute an md5 or sha1 hash of that 'somwthing' and then truncate it to whatever length you want.如果您的值不是完全随机的,但实际上可能取决于某些东西 - 您可以计算该“somwthing”的 md5 或 sha1 哈希,然后将其截断为您想要的任何长度。

Also you may generate and truncate a guid.您也可以生成和截断 guid。

Here is a mechanism to generate a random alpha-numeric string (I use this to generate passwords and test data) without defining the alphabet and numbers,这是一种生成随机字母数字字符串的机制(我用它来生成密码和测试数据)而不定义字母和数字,

CleanupBase64 will remove necessary parts in the string and keep adding random alpha-numeric letters recursively. CleanupBase64 将删除字符串中的必要部分并继续递归地添加随机字母数字字母。

        public static string GenerateRandomString(int length)
        {
            var numArray = new byte[length];
            new RNGCryptoServiceProvider().GetBytes(numArray);
            return CleanUpBase64String(Convert.ToBase64String(numArray), length);
        }

        private static string CleanUpBase64String(string input, int maxLength)
        {
            input = input.Replace("-", "");
            input = input.Replace("=", "");
            input = input.Replace("/", "");
            input = input.Replace("+", "");
            input = input.Replace(" ", "");
            while (input.Length < maxLength)
                input = input + GenerateRandomString(maxLength);
            return input.Length <= maxLength ?
                input.ToUpper() : //In my case I want capital letters
                input.ToUpper().Substring(0, maxLength);
        }

There is one of the awasome nuget packages that make this so simple.有一个 awasome nuget 软件包使这变得如此简单。

var myObject = new Faker<MyObject>()
.RuleFor(p => p.MyAlphaNumericProperty, f => f.Random.AlphaNumeric(/*lenght*/ 7))
.Generate();

One of the good example is here .这里就是一个很好的例子。

Using the new RandomNumberGenerator class and its static GetInt32 method:使用新RandomNumberGenerator class 及其 static GetInt32方法:

public string GenerateRandomString(int length, IEnumerable<char> charSet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789")
{
    var charArray = charSet.Distinct().ToArray();

    char[] result = new char[length];

    for (int i = 0; i < length; i++)
        result[i] = charArray[RandomNumberGenerator.GetInt32(charArray.Length)];

    return new string(result);
}

Very simple solution. 很简单的解决方案 It uses ASCII values and just generates "random" characters in between them. 它使用ASCII值,只在它们之间生成“随机”字符。

public static class UsernameTools
{
    public static string GenerateRandomUsername(int length = 10)
    {
        Random random = new Random();
        StringBuilder sbuilder = new StringBuilder();
        for (int x = 0; x < length; ++x)
        {
            sbuilder.Append((char)random.Next(33, 126));
        }
        return sbuilder.ToString();
    }

}

not 100% sure, as I didn't test EVERY option here, but of the ones I did test, this one is the fastest.不是 100% 确定,因为我没有测试这里的每个选项,但是在我测试的选项中,这个是最快的。 timed it with stopwatch and it showed 9-10 ticks so if speed is more important than security, try this:用秒表计时,它显示 9-10 个滴答声,所以如果速度比安全更重要,试试这个:

 private static Random random = new Random(); 
 public static string Random(int length)
     {   
          var stringChars = new char[length];

          for (int i = 0; i < length; i++)
              {
                  stringChars[i] = (char)random.Next(0x30, 0x7a);                  
                  return new string(stringChars);
              }
     }

You just use the assembly SRVTextToImage . 您只需使用程序集SRVTextToImage And write below code to generate random string. 并在下面写下代码来生成随机字符串。

CaptchaRandomImage c1 = new CaptchaRandomImage();
            string text = c1.GetRandomString(8);

Mostly it is used to implement the Captcha. 它主要用于实现Captcha。 But in your case it also works. 但在你的情况下它也有效。 Hope it helps. 希望能帮助到你。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM