If you're looking for a decent password strength control implementation for ASP.NET C# you could find this class I made a while ago useful enough. After all these years I'm still using it in a number of projects, from the good-old ASP.NET ASPX Forms to the new ASP.NET Core MVC applications.
The class can be used to perform basically all the required checks in a very customizable way: minimum length, maximum length, digit/numbers, special characters and so on. It features a PasswordStrength enum (and a GetPasswordStrength method) which you can use to calculate the average strength of any given password: it can be handy for general-purpose scenarios, when you don't have to implement a given password policy. In case you have to do that, you can use the helper methods instead and combine them to suit your needs as shown in the sample implementation provided within the IsStrongPassword method - which is the one I'm still using in most cases.
The methods are quite self-explanatory, so there isn't much more to say: if you like the class, feel free to leave a feedback in the comment section below!
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 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 |
using System; using System.Linq; using namespace Ryadel.Components.Security { public enum PasswordStrength { /// <summary> /// Blank Password (empty and/or space chars only) /// </summary> Blank = 0, /// <summary> /// Either too short (less than 5 chars), one-case letters only or digits only /// </summary> VeryWeak = 1, /// <summary> /// At least 5 characters, one strong condition met (>= 8 chars with 1 or more UC letters, LC letters, digits & special chars) /// </summary> Weak = 2, /// <summary> /// At least 5 characters, two strong conditions met (>= 8 chars with 1 or more UC letters, LC letters, digits & special chars) /// </summary> Medium = 3, /// <summary> /// At least 8 characters, three strong conditions met (>= 8 chars with 1 or more UC letters, LC letters, digits & special chars) /// </summary> Strong = 4, /// <summary> /// At least 8 characters, all strong conditions met (>= 8 chars with 1 or more UC letters, LC letters, digits & special chars) /// </summary> VeryStrong = 5 } public static class PasswordCheck { /// <summary> /// Generic method to retrieve password strength: use this for general purpose scenarios, /// i.e. when you don't have a strict policy to follow. /// </summary> /// <param name="password"></param> /// <returns></returns> public static PasswordStrength GetPasswordStrength(string password) { int score = 0; if (String.IsNullOrEmpty(password) || String.IsNullOrEmpty(password.Trim())) return PasswordStrength.Blank; if (HasMinimumLength(password, 5)) score++; if (HasMinimumLength(password, 8)) score++; if (HasUpperCaseLetter(password) && HasLowerCaseLetter(password)) score++; if (HasDigit(password)) score++; if (HasSpecialChar(password)) score++; return (PasswordStrength)score; } /// <summary> /// Sample password policy implementation: /// - minimum 8 characters /// - at lease one UC letter /// - at least one LC letter /// - at least one non-letter char (digit OR special char) /// </summary> /// <returns></returns> public static bool IsStrongPassword(string password) { return HasMinimumLength(password, 8) && HasUpperCaseLetter(password) && HasLowerCaseLetter(password) && (HasDigit(password) || HasSpecialChar(password)); } /// <summary> /// Sample password policy implementation following the Microsoft.AspNetCore.Identity.PasswordOptions standard. /// </summary> public static bool IsValidPassword(string password, PasswordOptions opts) { return IsValidPassword( password, opts.RequiredLength, opts.RequiredUniqueChars, opts.RequireNonAlphanumeric, opts.RequireLowercase, opts.RequireUppercase, opts.RequireDigit); } /// <summary> /// Sample password policy implementation following the Microsoft.AspNetCore.Identity.PasswordOptions standard. /// </summary> public static bool IsValidPassword( string password, int requiredLength, int requiredUniqueChars, bool requireNonAlphanumeric, bool requireLowercase, bool requireUppercase, bool requireDigit) { if (!HasMinimumLength(password, requiredLength)) return false; if (!HasMinimumUniqueChars(password, requiredUniqueChars)) return false; if (requireNonAlphanumeric && !HasSpecialChar(password)) return false; if (requireLowercase && !HasLowerCaseLetter(password)) return false; if (requireUppercase && !HasUpperCaseLetter(password)) return false; if (requireDigit && !HasDigit(password)) return false; return true; } #region Helper Methods public static bool HasMinimumLength(string password, int minLength) { return password.Length >= minLength; } public static bool HasMinimumUniqueChars(string password, int minUniqueChars) { return password.Distinct().Count() >= minUniqueChars; } /// <summary> /// Returns TRUE if the password has at least one digit /// </summary> public static bool HasDigit(string password) { return password.Any(c => char.IsDigit(c)); } /// <summary> /// Returns TRUE if the password has at least one special character /// </summary> public static bool HasSpecialChar(string password) { // return password.Any(c => char.IsPunctuation(c)) || password.Any(c => char.IsSeparator(c)) || password.Any(c => char.IsSymbol(c)); return password.IndexOfAny("!@#$%^&*?_~-£().,".ToCharArray()) != -1; } /// <summary> /// Returns TRUE if the password has at least one uppercase letter /// </summary> public static bool HasUpperCaseLetter(string password) { return password.Any(c => char.IsUpper(c)); } /// <summary> /// Returns TRUE if the password has at least one lowercase letter /// </summary> public static bool HasLowerCaseLetter(string password) { return password.Any(c => char.IsLower(c)); } #endregion } } |
It's worth noting that one of the methods (the one using PasswordOptions as a parameter) requires a reference to the using Microsoft.AspNetCore.Identity namespace: it will come very handy when using the ASP.NET Core Identity Framework to check the password validity at the server-side in some specific scenarios, such as new users registrations. If we don't want - or need - to add the Identity Framework to your project, we can just comment out that method and use the generic overload below.