1、密码要求
密码策略具体功能要求:
- (1)位长至少 8 位;
- (2)包括数字、小写字母、大写字母、特殊符号中至少 3 类;
- (3)不得包含用户名应更换系统的完整字符串、大小写变位或形似变换的字符串;
- (4)应更换系统 或设备出厂的默认口令;
- (5) 口令设置应避免键盘排序密码
- (6)支持定制密码修改频率;
- (7) 不得使用最近 N 次的密码;
2、代码实现
editPassword: [
{ required: true, trigger: "blur", message: "请输入新密码" },
{
min: 8,
max: 20,
message: "用户密码长度至少8位",
trigger: "blur",
},
{ required: true, validator: samePassword, trigger: "blur" },
],
confirmPassword: [
{ required: true, trigger: "blur", message: "请再次输入新密码" },
{ required: true, validator: equalToPassword, trigger: "blur" },
],
password: [
{ required: true, trigger: "blur", message: "请输入您的密码" },
{
pattern: /^.{8,}$/,
message: "用户密码长度必须大于8",
trigger: "blur",
},
{
pattern: /^(?![a-zA-Z]+$)(?![A-Z0-9]+$)(?![A-Z\W_!@#$%^&*`~()-+=]+$)(?![a-z0-9]+$)(?![a-z\W_!@#$%^&*`~()-+=]+$)(?![0-9\W_!@#$%^&*`~()-+=]+$)[a-zA-Z0-9\W_!@#$%^&*`~()-+=]/,
message: "密码应包含数字、大小写字母、特殊符号中的3类",
trigger: "blur",
},
{ required: true, validator: similarPassword, trigger: "blur" },
{ required: true, validator: sortPassword, trigger: "blur" },
],
package com.tianyuan.common.utils;
import java.util.ArrayList;
import java.util.List;
/**
* 密码校验工具类。
*
* @author tianyuan
*/
public class PassWordUtils {
public static boolean sortPassword(String str) {
char[][] keyCode = {
{'1', '2', '3', '4', '5', '6', '7', '8', '9', '0'},
{'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p'},
{'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';'},
{'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/'}};
char[] c = str.toCharArray();
List x = new ArrayList();
List y = new ArrayList();
for (int i = 0; i < c.length; ++i) {
char temp = c[i];
label358:
for (int j = 0; j < keyCode.length; ++j) {
for (int k = 0; k < keyCode[j].length; ++k) {
if (temp == keyCode[j][k]) {
x.add(Integer.valueOf(j));
y.add(Integer.valueOf(k));
break label358;
}
}
}
}
boolean flag = false;
for (int i = 0; i < x.size() - 2; ++i) {
if ((x.get(i) == x.get(i + 1)) && (x.get(i + 1) == x.get(i + 2))) {
if (((Integer) y.get(i)).intValue() > ((Integer) y.get(i + 2)).intValue()) {
if ((((Integer) y.get(i)).intValue() - 1 != ((Integer) y.get(i + 1)).intValue()) || (((Integer) y.get(i)).intValue() - 2 != ((Integer) y.get(i + 2)).intValue()))
continue;
flag = true;
break;
}
if ((((Integer) y.get(i)).intValue() + 1 != ((Integer) y.get(i + 1)).intValue()) || (((Integer) y.get(i)).intValue() + 2 != ((Integer) y.get(i + 2)).intValue()))
continue;
flag = true;
break;
}
if ((x.get(i) != x.get(i + 1)) && (x.get(i + 1) != x.get(i + 2)) && (x.get(i) != x.get(i + 2))) {
if (((Integer) x.get(i)).intValue() > ((Integer) x.get(i + 2)).intValue()) {
if ((((Integer) x.get(i)).intValue() - 1 != ((Integer) x.get(i + 1)).intValue()) || (((Integer) x.get(i)).intValue() - 2 != ((Integer) x.get(i + 2)).intValue()) ||
(y.get(i) != y.get(i + 1)) || (y.get(i) != y.get(i + 2))) continue;
flag = true;
break;
}
if ((((Integer) x.get(i)).intValue() + 1 != ((Integer) x.get(i + 1)).intValue()) || (((Integer) x.get(i)).intValue() + 2 != ((Integer) x.get(i + 2)).intValue()) ||
(y.get(i) != y.get(i + 1)) || (y.get(i) != y.get(i + 2))) continue;
flag = true;
break;
}
}
return flag;
}
//特殊形似字符
private static String SPECIALSTR = "1Ll|iI!";
// ! 形似 !i
private static String similar_tanhao = "!i";
// i 形似 iI!
private static String similar_lower_i = "iI!";
// I 形似 lL1I|i
private static String similar_upper_i = "lL1I|i";
// l 形似 lL1I|
private static String similar_lower_l = "lL1I|";
// L 形似 lL1I|
private static String similar_upper_l = "lL1I|";
// 1 形似 lL1I|
private static String similar_number_1 = "lL1I|";
// | 形似 lL1I|
private static String similar_separator = "lL1I|";
//校验标识
private static boolean flag = false;
/**
* 检查账号密码是否包含或大小写变位
*/
private static boolean checkPwdDeflection(String name, String pwd) {
String username = name.toLowerCase();
String password = pwd.toLowerCase();
if (password.equals(username)) {
return flag;
}
StringBuffer stbUsername = new StringBuffer();
StringBuffer stbPassword = new StringBuffer();
for (int j = 0; j < password.length(); j++) {
char c = password.charAt(j);
if (c == '0') {
c = 'o';
}
if (c == '1') {
c = 'l';
}
if (c == '2') {
c = 'z';
}
stbPassword.append(c);
}
for (int j = 0; j < username.length(); j++) {
char c = username.charAt(j);
if (c == '0') {
c = 'o';
}
if (c == '1') {
c = 'l';
}
if (c == '2') {
c = 'z';
}
stbUsername.append(c);
}
int i = (stbPassword.toString() + "").indexOf(stbUsername.toString());
if (i != -1) {
return flag;
}
return flag = true;
}
/**
* 检查账号密码是否形似
*/
public static boolean checkPwdSimilar(String name, String pwd) {
if (checkPwdDeflection(name, pwd)) {
flag = false;
}
//如果密码长度小于用户名长度不进行相关性校验
if (pwd.length() >= name.length()) {
flag = specialTrans(name, pwd);
}
return flag;
}
/**
* 密码的相似字符校验
*/
private static boolean specialTrans(String name, String pwd) {
boolean flag = false;
//对账号和密码进行普通的大小写转换(特殊形似字符不进行转换)
name = generalTrans(name);
pwd = generalTrans(pwd);
//用户名长度
int len = name.length();
//用户名第一个字符
String str = name.substring(0, 1);
int indexStart = 0;
List<String> list = new ArrayList<>();
//通过首字母判断有几个存在形似的字符串
if (SPECIALSTR.contains(str)) {
switch (str) {
case "i":
//形似 i ! I
for (int i = 0; i < similar_lower_i.length(); i++) {
pwdSplit(pwd, similar_lower_i.substring(i, i + 1), indexStart, len, list);
}
break;
case "!":
//形似 ! i
for (int i = 0; i < similar_tanhao.length(); i++) {
pwdSplit(pwd, similar_tanhao.substring(i, i + 1), indexStart, len, list);
}
break;
case "I":
//形似 l L 1 I | i
for (int i = 0; i < similar_upper_i.length(); i++) {
pwdSplit(pwd, similar_upper_i.substring(i, i + 1), indexStart, len, list);
}
break;
case "l":
//形似 l L 1 I |
for (int i = 0; i < similar_lower_l.length(); i++) {
pwdSplit(pwd, similar_lower_l.substring(i, i + 1), indexStart, len, list);
}
break;
case "L":
//形似 l L 1 I |
for (int i = 0; i < similar_upper_l.length(); i++) {
pwdSplit(pwd, similar_upper_l.substring(i, i + 1), indexStart, len, list);
}
break;
case "1":
//形似 l L 1 I |
for (int i = 0; i < similar_number_1.length(); i++) {
pwdSplit(pwd, similar_number_1.substring(i, i + 1), indexStart, len, list);
}
break;
case "|":
//形似 l L 1 I |
for (int i = 0; i < similar_separator.length(); i++) {
pwdSplit(pwd, similar_separator.substring(i, i + 1), indexStart, len, list);
}
break;
default:
break;
}
} else {
//判断name在pwd中存在几个可能的形似
pwdSplit(pwd, str, indexStart, len, list);
}
String tmp = "";
//循环拆分出来的list
for (int i = 0; i < list.size(); i++) {
//判断拆分出来的字符串数组,分别跟name对比
tmp = list.get(i);
//从name的第二个字符开始对比
for (int j = 1; j < name.length(); j++) {
String char1 = name.substring(j, j + 1);
String char2 = tmp.substring(j, j + 1);
//如果字符是特殊形似字符
if (SPECIALSTR.contains(char1)) {
if ("i".equals(char1)) {
if (!similar_lower_i.contains(char2)) {
break;
}
} else if ("!".equals(char1)) {
if (!similar_tanhao.contains(char2)) {
break;
}
} else if ("I".equals(char1)) {
if (!similar_upper_i.contains(char2)) {
break;
}
} else if ("l".equals(char1)) {
if (!similar_lower_l.contains(char2)) {
break;
}
} else if ("L".equals(char1)) {
if (!similar_upper_l.contains(char2)) {
break;
}
} else if ("1".equals(char1)) {
if (!similar_number_1.contains(char2)) {
break;
}
} else if ("|".equals(char1)) {
if (!similar_separator.contains(char2)) {
break;
}
}
} else if (!char1.equals(char2)) {
break;
}
//如果字符都一样
if (j == name.length() - 1) {
System.out.println("形似部分:" + tmp);
flag = true;
}
}
}
return flag;
}
/**
* 将密码分段进行校验
*/
private static void pwdSplit(String pwd, String str, int indexStart, int len, List<String> list) {
while (true) {
int tm = pwd.indexOf(str, indexStart);
if (tm >= 0) {
//如果首字符的位置+name的长度 大于 密码长度,说明不可能存在形似
if ((tm + len) <= pwd.length()) {
list.add(pwd.substring(tm, tm + len));
}
indexStart = tm + str.length();
} else {
indexStart = 0;
break;
}
}
}
/**
* 对普通的字符进行大小写转换(大小写、a/A=@、Z/z=2、O/o=0、S/s=$)
*/
private static String generalTrans(String str) {
//a
str = str.replace("A", "a");
str = str.replace("@", "a");
//b
str = str.replace("B", "b");
//c
str = str.replace("C", "c");
//d
str = str.replace("D", "d");
//e
str = str.replace("E", "e");
//f
str = str.replace("F", "f");
//g
str = str.replace("G", "g");
//h
str = str.replace("H", "h");
//i 形似:! I
//j
str = str.replace("J", "j");
//k
str = str.replace("K", "k");
//L形似:1 L l I |
//m
str = str.replace("M", "m");
//n
str = str.replace("N", "n");
//o
str = str.replace("O", "o");
str = str.replace("0", "o");
//p
str = str.replace("P", "p");
//r
str = str.replace("R", "r");
//s
str = str.replace("S", "s");
str = str.replace("$", "s");
//t
str = str.replace("T", "t");
//u
str = str.replace("U", "u");
//v
str = str.replace("V", "v");
//w
str = str.replace("W", "w");
//x
str = str.replace("x", "x");
//y
str = str.replace("Y", "y");
//z
str = str.replace("Z", "z");
str = str.replace("2", "z");
return str;
}
}