ASP.NET Identity : Generate random password
是否有任何内置函数可以创建随机密码?ASP.NET Simple Membership以前有类似的方法
尽管我参加聚会有点晚,但我还是想分享我组合起来的帮助器方法,以一种与ASP.NET核心兼容的方式处理这些场景。
下面的函数确保了一个像样的字符分布,在字符串中随机添加所需的字符类型,并且不会改变所需的长度(除非具有大量所需的唯一字符的边缘情况,这是设计所指的)。它还提供了对
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | /// <summary> /// Generates a Random Password /// respecting the given strength requirements. /// </summary> /// <param name="opts">A valid PasswordOptions object /// containing the password strength requirements.</param> /// <returns>A random password</returns> public static string GenerateRandomPassword(PasswordOptions opts = null) { if (opts == null) opts = new PasswordOptions() { RequiredLength = 8, RequiredUniqueChars = 4, RequireDigit = true, RequireLowercase = true, RequireNonAlphanumeric = true, RequireUppercase = true }; string[] randomChars = new[] { "ABCDEFGHJKLMNOPQRSTUVWXYZ", // uppercase "abcdefghijkmnopqrstuvwxyz", // lowercase "0123456789", // digits "!@$?_-" // non-alphanumeric }; Random rand = new Random(Environment.TickCount); List<char> chars = new List<char>(); if (opts.RequireUppercase) chars.Insert(rand.Next(0, chars.Count), randomChars[0][rand.Next(0, randomChars[0].Length)]); if (opts.RequireLowercase) chars.Insert(rand.Next(0, chars.Count), randomChars[1][rand.Next(0, randomChars[1].Length)]); if (opts.RequireDigit) chars.Insert(rand.Next(0, chars.Count), randomChars[2][rand.Next(0, randomChars[2].Length)]); if (opts.RequireNonAlphanumeric) chars.Insert(rand.Next(0, chars.Count), randomChars[3][rand.Next(0, randomChars[3].Length)]); for (int i = chars.Count; i < opts.RequiredLength || chars.Distinct().Count() < opts.RequiredUniqueChars; i++) { string rcs = randomChars[rand.Next(0, randomChars.Length)]; chars.Insert(rand.Next(0, chars.Count), rcs[rand.Next(0, rcs.Length)]); } return new string(chars.ToArray()); } |
函数以
在可能的情况下,您在ASP.NET核心项目中拥有它,在定义密码要求时,可以使用与startup类的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | [...] // Add ASP.NET Identity support services.AddIdentity<ApplicationUser, IdentityRole>( opts => { opts.Password.RequireDigit = true; opts.Password.RequireLowercase = true; opts.Password.RequireUppercase = true; opts.Password.RequireNonAlphanumeric = false; opts.Password.RequiredLength = 7; }) .AddEntityFrameworkStores<ApplicationDbContext>(); [...] |
有关此帮助程序功能的其他详细信息,您也可以在我的博客上阅读此文章。
您使用的是什么框架?
在这里检查:
1 | string password = Membership.GeneratePassword(12, 1); |
ASP.NET标识没有生成密码方法。
我不确定您的确切使用情况,但我相信最好的方法是向用户发送一个重置密码链接,允许用户输入自己的密码。这通常被认为比用纯文本发送生成的密码更安全。
请参见本教程中的"重置密码"部分:http://www.asp.net/identity/overview/features-api/account-confirmation-and-password-recovery-with-aspnet-identity
我编写了一个简单的函数,它考虑使用usermanager验证器来创建一个随机分配给用户的密码。
它只生成随机字符并检查字符是否满足验证器要求。如果不满足需求,它将附加剩余的字符以满足规则。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | private string GeneratePassword(MessagePasswordValidator validator) { if (validator == null) return null; bool requireNonLetterOrDigit = validator.RequireNonLetterOrDigit; bool requireDigit = validator.RequireDigit; bool requireLowercase = validator.RequireLowercase; bool requireUppercase = validator.RequireUppercase; string randomPassword = string.Empty; int passwordLength = validator.RequiredLength; Random random = new Random(); while (randomPassword.Length != passwordLength) { int randomNumber = random.Next(48, 122); // >= 48 && < 122 if (randomNumber == 95 || randomNumber == 96) continue; // != 95, 96 _' char c = Convert.ToChar(randomNumber); if (requireDigit) if (char.IsDigit(c)) requireDigit = false; if (requireLowercase) if (char.IsLower(c)) requireLowercase = false; if (requireUppercase) if (char.IsUpper(c)) requireUppercase = false; if (requireNonLetterOrDigit) if (!char.IsLetterOrDigit(c)) requireNonLetterOrDigit = false; randomPassword += c; } if (requireDigit) randomPassword += Convert.ToChar(random.Next(48, 58)); // 0-9 if (requireLowercase) randomPassword += Convert.ToChar(random.Next(97, 123)); // a-z if (requireUppercase) randomPassword += Convert.ToChar(random.Next(65, 91)); // A-Z if (requireNonLetterOrDigit) randomPassword += Convert.ToChar(random.Next(33, 48)); // symbols !"#$%&'()*+,-./ return randomPassword; } |
呼唤:
1 | string password = GeneratePassword(UserManager.PasswordValidator as MessagePasswordValidator); |
我知道这是一个有点老套的问题,还有一些人提出了随机生成密码的来源,但是membership.generatePassword的实现方式如下:
幸运的是,这是在麻省理工学院许可证下获得的许可:https://github.com/microsoft/referencesource/blob/master/license.txt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | public class PasswordStore { private static readonly char[] Punctuations ="!@#$%^&*()_-+=[{]};:>|./?".ToCharArray(); private static readonly char[] StartingChars = new char[] { '<', '&' }; /// <summary>Generates a random password of the specified length.</summary> /// <returns>A random password of the specified length.</returns> /// <param name="length">The number of characters in the generated password. The length must be between 1 and 128 characters. </param> /// <param name="numberOfNonAlphanumericCharacters">The minimum number of non-alphanumeric characters (such as @, #, !, %, &, and so on) in the generated password.</param> /// <exception cref="T:System.ArgumentException"> /// <paramref name="length" /> is less than 1 or greater than 128 -or-<paramref name="numberOfNonAlphanumericCharacters" /> is less than 0 or greater than <paramref name="length" />. </exception> public static string GeneratePassword(int length, int numberOfNonAlphanumericCharacters) { if (length < 1 || length > 128) throw new ArgumentException("password_length_incorrect", nameof(length)); if (numberOfNonAlphanumericCharacters > length || numberOfNonAlphanumericCharacters < 0) throw new ArgumentException("min_required_non_alphanumeric_characters_incorrect", nameof(numberOfNonAlphanumericCharacters)); string s; int matchIndex; do { var data = new byte[length]; var chArray = new char[length]; var num1 = 0; new RNGCryptoServiceProvider().GetBytes(data); for (var index = 0; index < length; ++index) { var num2 = (int)data[index] % 87; if (num2 < 10) chArray[index] = (char)(48 + num2); else if (num2 < 36) chArray[index] = (char)(65 + num2 - 10); else if (num2 < 62) { chArray[index] = (char)(97 + num2 - 36); } else { chArray[index] = Punctuations[num2 - 62]; ++num1; } } if (num1 < numberOfNonAlphanumericCharacters) { var random = new Random(); for (var index1 = 0; index1 < numberOfNonAlphanumericCharacters - num1; ++index1) { int index2; do { index2 = random.Next(0, length); } while (!char.IsLetterOrDigit(chArray[index2])); chArray[index2] = Punctuations[random.Next(0, Punctuations.Length)]; } } s = new string(chArray); } while (IsDangerousString(s, out matchIndex)); return s; } internal static bool IsDangerousString(string s, out int matchIndex) { //bool inComment = false; matchIndex = 0; for (var i = 0; ;) { // Look for the start of one of our patterns var n = s.IndexOfAny(StartingChars, i); // If not found, the string is safe if (n < 0) return false; // If it's the last char, it's safe if (n == s.Length - 1) return false; matchIndex = n; switch (s[n]) { case '<': // If the < is followed by a letter or '!', it's unsafe (looks like a tag or HTML comment) if (IsAtoZ(s[n + 1]) || s[n + 1] == '!' || s[n + 1] == '/' || s[n + 1] == '?') return true; break; case '&': // If the & is followed by a #, it's unsafe (e.g. S) if (s[n + 1] == '#') return true; break; } // Continue searching i = n + 1; } } private static bool IsAtoZ(char c) { if ((int)c >= 97 && (int)c <= 122) return true; if ((int)c >= 65) return (int)c <= 90; return false; } } |
https://msdn.microsoft.com/ru-ru/library/system.guid.newguid(v=vs.110).aspx看看这个。guid应该可以正常工作(只需从中删除所有的"-"并剪切所需的字符数)