需求:用js检测纯数字密码的强弱,检测规则可以如下:
1)不能3位以上的数字相邻;(123895,321874)
2)不能3位以上的数字相同;(111895)
3)不能重复2组以上的数字;(898923,121212,768768)
4)不能疑似生日数字:(890207,791211)
5)不能回文数字:(653356,125521)
思路
1、不能3位以上的数字相邻
循环整个字符串,用后一位数字减去前一位数字,取两者差值的绝对值,如果差值的绝对值等于1则表示前后2位数字相邻。为什么要取差值的绝对值?
因为密码中的数字可能是正序的,也有可能是倒序的,如:123985
、654028
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
特别鸣谢: @正则奇之,感谢这位大佬提供了正则及思路