需求:用js检测纯数字密码的强弱,检测规则可以如下:

1)不能3位以上的数字相邻;(123895,321874)
2)不能3位以上的数字相同;(111895)
3)不能重复2组以上的数字;(898923,121212,768768)
4)不能疑似生日数字:(890207,791211)
5)不能回文数字:(653356,125521)

思路

1、不能3位以上的数字相邻
循环整个字符串,用后一位数字减去前一位数字,取两者差值的绝对值,如果差值的绝对值等于1则表示前后2位数字相邻。
为什么要取差值的绝对值?
  因为密码中的数字可能是正序的,也有可能是倒序的,如:123985654028

2、不能3位以上的数字相同
使用正则即可:/([0-9])\1{2}/

3、不能重复2组以上的数字
使用正则:/([0-9]{2,})\1/
如果中间间隔其他字符,可以在中间加上[0-9]*)

4、不能疑似生日数字
使用正则:
  年份正则:/([0-9][0-9])/;取密码的前2位进行判断
  月份正则:/(0[1-9]|1[012])/;取密码的中间2位进行判断
  日期正则:/([12][0-9]|0[1-9]|3[01])/;取密码的后2位进行判断

5、不能回文数字
什么是回文数字?
  正着读与反着读都一样的就是回文数字!简单点就是:正反都一样的就是回文数字
既然回文数字正反都一样,那么只需要将数字密码反转过来再与原始密码进行比较即可,如果一样那就说明是回文数字

代码实现

function numberWeakPasswordCheck (pwd, options) {
  if (!options) {
    options = {};
  }
  
  var result = 1;
  var lengthMin = options.lengthMin || 6; // 密码最小长度
  var adjacentNumberCount = options.adjacentNumberCount; // 连续相邻数字数量,如:845630、123956
  if (!adjacentNumberCount && adjacentNumberCount !== 0) {
    adjacentNumberCount = 3;
  }
  var continuousDuplecatedCharsCount = options.continuousDuplecatedCharsCount; // 连续重复字符数量,111234
  if (!continuousDuplecatedCharsCount && continuousDuplecatedCharsCount !== 0) {
    continuousDuplecatedCharsCount = 3;
  }
  var continuousDuplecatedGroupdCharsCount = options.continuousDuplecatedGroupdCharsCount; // 连续重复分组字符数量,如:121245、12312368
  if (!continuousDuplecatedGroupdCharsCount && continuousDuplecatedGroupdCharsCount !== 0) {
    continuousDuplecatedGroupdCharsCount = 2;
  }
  var allowPalindrome = options.allowPalindrome || false; // 是否允许回文字符,如:783387
  var allowBirthday = options.allowBirthday || false; // 是否允许生日日期组合,如:950127
  
  if (typeof pwd == "number") {
    pwd = pwd + '';
  }
  if (typeof pwd != 'string') {
    return {
      isWeak: true,
      code: -1
    };
  }
  pwd = pwd.trim();
  if (!/^\d+$/.test(pwd)) {
    return {
      isWeak: true,
      code: -2
    };
  }
  if (pwd.length < lengthMin) {
    console.log('密码长度小于', lengthMin, pwd);
    return {
      isWeak: true,
      code: 2
    };
  }

  if (continuousDuplecatedCharsCount !== 0) {
    continuousDuplecatedCharsCount = Math.ceil(Math.abs(parseFloat(continuousDuplecatedCharsCount)));
    // 连续重复字符数量正则,如:/([0-9]\1{2})/
    var continuousDuplecatedCharsReg = new RegExp('([0-9])\\1\{' + (continuousDuplecatedCharsCount - 1) + '\}');
    if (continuousDuplecatedCharsReg.test(pwd)) {
      console.log('密码中包含' + continuousDuplecatedCharsCount + '个字符的连续重复字符数量', pwd);
      return {
        isWeak: true,
        code: 3
      };
    }
  }
  
  if (continuousDuplecatedGroupdCharsCount !== 0) {
    continuousDuplecatedGroupdCharsCount = Math.ceil(Math.abs(parseFloat(continuousDuplecatedGroupdCharsCount)));
    // 连续重复分组字符数量正则,如:/([0-9]{2,})\1/
    var continuousDuplecatedGroupdCharsReg = new RegExp('([0-9]\{'+ continuousDuplecatedGroupdCharsCount +',\})\\1');
    if (continuousDuplecatedGroupdCharsReg.test(pwd)) {
      console.log('密码中包含' + continuousDuplecatedGroupdCharsCount + '个字符的连续重复字符组', pwd);
      return {
        isWeak: true,
        code: 4
      };
    }
  }

  if (adjacentNumberCount !== 0) { // 判断连续相邻数字
    adjacentNumberCount = Math.ceil(Math.abs(parseFloat(adjacentNumberCount))) - 1;
    var pwdArr = pwd.split('');
    var count = 0;
    var minuendNumber = pwdArr[0]; // 被减数
    
    var firstMatchedDiff = 0; // 首次相邻字符相减差值为1时的差值结果
    for (var i = 1, len = pwdArr.length; i < len; i++) {
      var numberItem = pwdArr[i];
      var diff = minuendNumber - numberItem;
      if (Math.abs(diff) === 1 && ( firstMatchedDiff == 0 || (firstMatchedDiff > 0 ? (minuendNumber > numberItem) : (minuendNumber < numberItem)))) {
        count++;
        firstMatchedDiff = diff;
      } else { // 如果前后数字相减不等于1那么count需置为0,如果不置0则会出现非连续相邻数字也会被视为连续相邻数字
        count = 0;
        firstMatchedDiff = 0;
      }
      minuendNumber = numberItem;
      if (count >= adjacentNumberCount) {
        break;
      }
    }
    if (count >= adjacentNumberCount) {
      console.log('密码中包含' + (adjacentNumberCount + 1) + '位或以上的相邻数字', pwd);
      return {
        isWeak: true,
        code: 5
      };
    }
  }

  if (!allowPalindrome) { // 判断回文字符
    var pwdArr = pwd.split('');
    if (pwdArr.reverse().join('') === pwd) {
      console.log('密码为回文字符', pwd);
      return {
        isWeak: true,
        code: 6
      };
    }
  }

  if (!allowBirthday && pwd.length >= 6) { // 判断生日日期组合
    var yearReg = /([0-9][0-9])/;
    var monthReg = /(0[1-9]|1[012])/;
    var dayReg = /([12][0-9]|0[1-9]|3[01])/;
    if (yearReg.test(pwd.substr(0, 2)) && monthReg.test(pwd.substr(2, 2)) && dayReg.test(pwd.substr(4, 2))) {
      console.log('密码疑似为生日日期组合', pwd);
      return {
        isWeak: true,
        code: 7
      };
    }
  }

  return {
    isWeak: false,
    code: 1
  };
}

code解释:

  • -1: 密码非字符串
  • -2: 密码非全数字
  • 1: 非弱密码
  • 2: 密码长度小于6位
  • 3: 密码中包含3个字符的连续重复字符数量
  • 4: 密码中包含2个字符的连续重复字符组
  • 5: 密码中包含3位或以上的相邻数字
  • 6: 密码为回文字符
  • 7: 密码疑似为生日日期组合

示例密码:
【连续重复字符】:111234、233314、545666
【连续重复分组字符】:121245、156561、253838
【相邻数字】:321874、678968、456321、123895
【回文字符】:653356、125621、125521
【生日日期】:950127、001120、890207

特别鸣谢: @正则奇之,感谢这位大佬提供了正则及思路


heath_learning
1.4k 声望31 粉丝