[C#]正则表达式验证密码是否符合规则

0x00 一句话

如果想直接使用解决方案的话,可以参考下列代码即可实现。
下面的正则表达式设置了5个规则。

  1. 必须包含一个小写字母。
  2. 必须包含一个大写字母。
  3. 必须包含一个数字。
  4. 必须包含一个特殊符号,定义于Password special characters
  5. 长度必须在8-32之间。

下列的 PASSWORD_STRENGTH_1 和 PASSWORD_STRENGTH_2等价,
只是不同的写法,
PASSWORD_STRENGTH_1把各个逻辑块分开了,便于理解。

        /// 
        /// 包含小写字母
        /// 
        private static readonly string REG_CONTAIN_LOWERCASE_ASSERTION =
            @"(?=.*[a-z])";

        /// 
        /// 包含大写字母
        /// 
        private static readonly string REG_CONTAIN_UPPERCASE_ASSERTION =
            @"(?=.*[A-Z])";

        /// 
        /// 包含数字
        /// 
        private static readonly string REG_CONTAIN_DIGIT_ASSERTION =
            @"(?=.*\d)";

        /// 
        /// 包含特殊字符(https://www.owasp.org/index.php/Password_special_characters)
        /// 
        private static readonly string REG_CONTAIN_SPECIAL_CHAR_ASSERTION =
            @"(?=.*[ !""#$%&'()*+,-./:;<=>?@\[\]\^_`{|}~])";

        public static readonly string PASSWORD_STRENGTH_1 =
            $"{REG_CONTAIN_LOWERCASE_ASSERTION}" + 
            $"{REG_CONTAIN_UPPERCASE_ASSERTION}" + 
            $"{REG_CONTAIN_DIGIT_ASSERTION}" + 
            $"{REG_CONTAIN_SPECIAL_CHAR_ASSERTION}" +
            @"^.{8,32}$";
            
        /// 
        /// PASSWORD_STRENGTH_1 的另一种写法
        /// 
		public static readonly string PASSWORD_STRENGTH_2 = @"(?=(.*[a-z]))(?=(.*[A-Z]))(?=(.*\d))(?=(.*[ !""#$%&'()*+,-./:;<=>?@\[\]\^_`{|}~]))^.{8,32}$";

        public static void TestPattern(string pattern, string input)
        {
            Regex regex = new Regex(pattern);
            Console.WriteLine(regex.IsMatch(input));
        }

0x01 Prerequisite

阅读下列内容需要对以下的内容有涉猎。

  • 正则表达式的基本概念
  • C#创建String语法: 《C# Special Characters》

0x02 Emmm,一点废话

在软件行业里,和数据可以说是密不可分。我们所写的代码本质就是为数据服务。
传输数据、对数据做变换、数据存储等等。
软件里有很多种数据,有int、string、float、double、Decimal等。而对于有UI的客户端来说,在画面上显示的大部分都是字符串、而从画面上由用户键盘输入的也大部分都是字符串。别的Audio/Video数据本文暂不讨论。
所以这里有三个概念要提及。

  1. 格式化(Formating): 把数据按照一定的格式(format)转换成字符串便于显示在画面上。
  2. 校验(Validation): 校验用户输入是否符合规则比如密码强度是否达标,输入的年龄是否是正常范围的数字等。
  3. 解析(Parsing): 把用户输入的字符串按照一定规则解析到指定的数据类型上,这个数据类型可以是DateTime、Double、Decimal、Boolean也可以是Object。

而正则表达式则是验证数据的好帮手,主流的编程语言都会支持正则表达式。本文要解决的问题就是“如何使用正则表达式验证密码是否符合某种规则?“

0x03 那么,如何使用正则表达式验证密码是否符合某种规则?

为了实现这个目标,我们需要用到正则表达式里的一个概念叫做零宽度正预测先行断言(Zero-Width Positive Lookahead Assertions)。
长这个样子,

(?= 子表达式 )

使用这个构造便能够在正则表达式里使用先行断言了。可以参考以下例子。

        public static void Test()
        {
            Regex regex = new Regex(@"(?=.*12)^.*$"); // 匹配是否有12的序列
            Console.WriteLine(regex.IsMatch("23312312")); // True
        }

        public static void Test2()
        {
            Regex regex = new Regex(@"(?=.*\d)^.*$"); // 是否至少有一个数字
            Console.WriteLine(regex.IsMatch("Aadakjdhak!@#!$")); // False
            Console.WriteLine(regex.IsMatch("Aadakjdhak!1#!$")); // True
        }

而当我们想实现文章最开始提到的5个规则的时候,依次实现即可。

@"(?=.*[a-z])" // 包含一个小写字母
@"(?=.*[A-Z])" // 包含一个大写字母
@"(?=.*\d)" // 包含一个数字
@"(?=.*[ !""#$%&'()*+,-./:;<=>?@\[\]\^_`{|}~])"; // 包含一个特殊字符 
@"^.{8,32}$ // 长度限制,匹配 \n以外的任何单字符8-32次。'.'可以替换成任意的字符类(Character class)

以上的各个Pattern字符串拼接起来便能实现验证密码强度是否这5个规则了。

0x04 结语

数据验证是保证程序安全正确运行不可或缺的一步。错误的输入会导致不可预想的后果。
在《Effective Java The 3rd Edition》中

Item62: Avoid strings where other types are more appropriate.

讲到在存储用户输入数据时候,除非输入的数据就是文本类型,否则请转换成对于的正确的类型。而用户输入数据一定一定要做验证,因为你永远不知道你的用户会输入什么样奇葩的数据。
而验证数据最好的帮手之一,一定有正则表达式,学一点点正则表达式,能让数据验证更加简单。

你可能感兴趣的:(#,C#,#,正则表达式,C#,正则表达式,密码验证)