> 文章列表 > JAVA集成强密码校验

JAVA集成强密码校验

JAVA集成强密码校验

JAVA集成强密码校验

    • 1 : 背景
    • 2 : 代码设计编写
      • 2.1 : 引入规则配置
      • 2.2 : 密码校验工具类
    • 3 : 验证
    • 4 : 相关链接

1 : 背景

最近系统需要做用户密码升级,增加强密码校验,密码长度,复杂度等等,所以整理了一份通用的密码复杂度控制代码。
目的:实现一套拿来即用的密码验证功能,可灵活配置,随意挑选规则。需实现可复用性,可迁移性等。

1、引入密码等级概念。
即框定规则,等级数为满足规则的数量,这样等级越高,规则越复杂。
但缺点为不可控,故放弃次方式。
2、仅引入密码开关,密码规则概念。
密码开关做总控,密码规则开关做细分管控,方便随意搭配密码规则。

2 : 代码设计编写

2.1 : 引入规则配置

1、密码检测总控开关
2、密码长度控制开关
3、数字、小写字母、大写字母、特殊符号控制开关
4、键盘横向连续检测开关,如qwer等
5、键盘斜向连续检测开关
6、逻辑位置连续检测开关,如1234、abcd等
7、相邻字符相同检测开关,如aaaa、1111、#等
8、自定义密码检测开关,如固定字符等
由此引入yml配置如下
application.yml

server:port: 8080servlet:context-path: /projectpassword:#密码检测总控开关passwordCheckSwitch: true#密码长度控制开关checkPasswordLength: truelimitPasswordMinLength: 8limitPasswordMaxLength: 20#数字、小写字母、大写字母、特殊符号控制开关checkContainDigit: truecheckContainUpperLowerCase: falsecheckContainLowerCase: truecheckContainUpperCase: truecheckContainSpecialChar: falsedefaultSpecialChar: "!\\"#$%&'()*+,-./:;<=>?@[\\\\]^_`{|}~"#键盘横向连续检测开关,如qwer等checkHorizontalKeySequential: falselimitHorizontalKeyNumber: 3#键盘斜向连续检测开关checkSlopeKeySequential: falselimitSlopeKeyNumber: 3#逻辑位置连续检测开关,如1234、abcd等checkLogicSequential: falselimitLogicNumber: 3#相邻字符相同检测开关,如aaaa、1111、#等checkSequentialCharSame: falselimitSequentialCharNumber: 3#自定义密码检测开关,如固定字符等checkCustomPasswordArray: true

引入自定义密码文件:password.txt

123456
123456789
1234567890
1234561314
admin1234
test1234
123abc

以上配置引入,在代码中如何注入,可参考文末链接。

对应配置类 PasswordConfigBean.java

package com.bean;import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.List;@Component
public class PasswordConfigBean {//开关->开public final static String PASS_WORD_STATUS_TRUE = "true";//开关->关public final static String PASS_WORD_STATUS_FALSE = "false";//密码检测开关public static volatile String PASS_WORD_CHECK_SWITCH;//是否检测密码口令长度标识public static volatile String CHECK_PASSWORD_LENGTH;//密码最小长度public static volatile String LIMIT_PASSWORD_MIN_LENGTH;//密码最大长度public static volatile String LIMIT_PASSWORD_MAX_LENGTH;//是否包含数字public static volatile String CHECK_CONTAIN_DIGIT;//是否区分大小写public static volatile String CHECK_CONTAIN_UPPER_LOWER_CASE;//是否包含小写字母public static volatile String CHECK_CONTAIN_LOWER_CASE;//是否包含大写字母public static volatile String CHECK_CONTAIN_UPPER_CASE;//是否包含特殊符号public static volatile String CHECK_CONTAIN_SPECIAL_CHAR;//特殊符号集合public static volatile String DEFAULT_SPECIAL_CHAR;//是否检测键盘按键横向连续public static volatile String CHECK_HORIZONTAL_KEY_SEQUENTIAL;//键盘物理位置横向不允许最小的连续个数public static volatile String LIMIT_HORIZONTAL_KEY_NUMBER;//是否检测键盘按键斜向连续public static volatile String CHECK_SLOPE_KEY_SEQUENTIAL;//键盘物理位置斜向不允许最小的连续个数public static volatile String LIMIT_SLOPE_KEY_NUMBER;//是否检测逻辑位置连续public static volatile String CHECK_LOGIC_SEQUENTIAL;//密码口令中字符在逻辑位置上不允许最小的连续个数public static volatile String LIMIT_LOGIC_NUMBER;//是否检测连续字符相同public static volatile String CHECK_SEQUENTIAL_CHAR_SAME;//密码口令中相同字符不允许最小的连续个数public static volatile String LIMIT_SEQUENTIAL_CHAR_NUMBER;//是否校验自定义密码集合public static volatile String CHECK_CUSTOM_PASSWORD_ARRAY;//自定义密码集合public static volatile List<String> CUSTOM_PASSWORD_ARRAY = new ArrayList<>();//键盘横向方向规则public static volatile String[] KEYBOARD_HORIZONTAL_ARR = {"01234567890", "qwertyuiop", "asdfghjkl", "zxcvbnm"};//键盘斜线方向规则public static volatile String[] KEYBOARD_SLOPE_ARR = {"1qaz", "2wsx", "3edc", "4rfv", "5tgb", "6yhn", "7ujm", "8ik,", "9ol.", "0p;/", "=[;.", "-pl,", "0okm", "9ijn", "8uhb", "7ygv", "6tfc", "5rdx", "4esz","!QAZ", "@WSX", "#EDC", "$RFV", "%TGB", "^YHN", "&UJM", "*IK<", "(OL>", ")P:?", "+{:>", "_PL<", ")OKM", "(IJN", "*UHB", "&YGV", "^TFC", "%RDX", "$ESZ"};}

对应配置类 PasswordConfigBeanSet.java

package com.bean;import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Component;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Arrays;@Component
public class PasswordConfigBeanSet {@Value("${password.passwordCheckSwitch}")public static void setPasswordCheckSwitch(String passwordCheckSwitch) {PasswordConfigBean.PASS_WORD_CHECK_SWITCH = passwordCheckSwitch;}@Value("${password.checkPasswordLength}")private static void setCheckPasswordLength(String checkPasswordLength) {PasswordConfigBean.CHECK_PASSWORD_LENGTH = checkPasswordLength;}@Value("${password.limitPasswordMinLength}")private void setLimitPasswordMinLength(String limitPasswordMinLength) {PasswordConfigBean.LIMIT_PASSWORD_MIN_LENGTH = limitPasswordMinLength;}@Value("${password.limitPasswordMaxLength}")private void setLimitPasswordMaxLength(String limitPasswordMaxLength) {PasswordConfigBean.LIMIT_PASSWORD_MAX_LENGTH = limitPasswordMaxLength;}@Value("${password.checkContainDigit}")private void setCheckContainDigit(String checkContainDigit) {PasswordConfigBean.CHECK_CONTAIN_DIGIT = checkContainDigit;}@Value("${password.checkContainUpperLowerCase}")private void setCheckContainUpperLowerCase(String checkContainUpperLowerCase) {PasswordConfigBean.CHECK_CONTAIN_UPPER_LOWER_CASE = checkContainUpperLowerCase;}@Value("${password.checkContainLowerCase}")private void setCheckContainLowerCase(String checkContainLowerCase) {PasswordConfigBean.CHECK_CONTAIN_LOWER_CASE = checkContainLowerCase;}@Value("${password.checkContainUpperCase}")private void setCheckContainUpperCase(String checkContainUpperCase) {PasswordConfigBean.CHECK_CONTAIN_UPPER_CASE = checkContainUpperCase;}@Value("${password.checkContainSpecialChar}")private void setCheckContainSpecialChar(String checkContainSpecialChar) {PasswordConfigBean.CHECK_CONTAIN_SPECIAL_CHAR = checkContainSpecialChar;}@Value("${password.defaultSpecialChar}")private void setDefaultSpecialChar(String defaultSpecialChar) {PasswordConfigBean.DEFAULT_SPECIAL_CHAR = defaultSpecialChar;}@Value("${password.checkHorizontalKeySequential}")private void setCheckHorizontalKeySequential(String checkHorizontalKeySequential) {PasswordConfigBean.CHECK_HORIZONTAL_KEY_SEQUENTIAL = checkHorizontalKeySequential;}@Value("${password.limitHorizontalKeyNumber}")private void setLimitHorizontalKeyNumber(String limitHorizontalKeyNumber) {PasswordConfigBean.LIMIT_HORIZONTAL_KEY_NUMBER = limitHorizontalKeyNumber;}@Value("${password.checkSlopeKeySequential}")private void setCheckSlopeKeySequential(String checkSlopeKeySequential) {PasswordConfigBean.CHECK_SLOPE_KEY_SEQUENTIAL = checkSlopeKeySequential;}@Value("${password.limitSlopeKeyNumber}")private void setLimitSlopeKeyNumber(String limitSlopeKeyNumber) {PasswordConfigBean.LIMIT_SLOPE_KEY_NUMBER = limitSlopeKeyNumber;}@Value("${password.checkLogicSequential}")private void setCheckLogicSequential(String checkLogicSequential) {PasswordConfigBean.CHECK_LOGIC_SEQUENTIAL = checkLogicSequential;}@Value("${password.limitLogicNumber}")private void setLimitLogicNumber(String limitLogicNumber) {PasswordConfigBean.LIMIT_LOGIC_NUMBER = limitLogicNumber;}@Value("${password.checkSequentialCharSame}")private void setCheckSequentialCharSame(String checkSequentialCharSame) {PasswordConfigBean.CHECK_SEQUENTIAL_CHAR_SAME = checkSequentialCharSame;}@Value("${password.limitSequentialCharNumber}")private void setLimitSequentialCharNumber(String limitSequentialCharNumber) {PasswordConfigBean.LIMIT_SEQUENTIAL_CHAR_NUMBER = limitSequentialCharNumber;}@Value("${password.checkCustomPasswordArray}")private void setCheckCustomPasswordArray(String checkCustomPasswordArray) {PasswordConfigBean.CHECK_CUSTOM_PASSWORD_ARRAY = checkCustomPasswordArray;if("true".equals(checkCustomPasswordArray)){loadCustomPasswordArray();}}//加载自定义密码private static void loadCustomPasswordArray() {BufferedReader bufferedReader = null;ClassPathResource classPathResource = new ClassPathResource("password.txt");try (InputStream inputStream = classPathResource.getInputStream();InputStreamReader inputStreamReader = new InputStreamReader(inputStream);){bufferedReader = new BufferedReader(inputStreamReader);String line;while(null != (line = bufferedReader.readLine())) {PasswordConfigBean.CUSTOM_PASSWORD_ARRAY.add(line);}} catch (IOException var5) {PasswordConfigBean.CUSTOM_PASSWORD_ARRAY.addAll(Arrays.asList(("123456,Qwer,111111,123456789,test1234").split(",")));}}
}

2.2 : 密码校验工具类

PasswordCheckUtil.java

package com.utils;import com.bean.PasswordConfigBean;
import java.util.Iterator;public class PasswordCheckUtil {public static boolean checkPassword(String password) {if (password == null || "".equals(password)) {return false;}//密码校验总开关if (PasswordConfigBean.PASS_WORD_STATUS_FALSE.equals(PasswordConfigBean.PASS_WORD_CHECK_SWITCH)){return true;}//是否在自定义集合中if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_CUSTOM_PASSWORD_ARRAY) && checkCustomPasswordArray(password)){return false;}//检测长度if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_PASSWORD_LENGTH) && !checkPasswordLength(password, PasswordConfigBean.LIMIT_PASSWORD_MAX_LENGTH, PasswordConfigBean.LIMIT_PASSWORD_MIN_LENGTH)){return false;}//检测包含数字if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_CONTAIN_DIGIT) && !password.matches("(.*[0-9].*)")){return false;}//检测包含字母(区分大小写)if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_CONTAIN_UPPER_LOWER_CASE)){//检测包含小写字母if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_CONTAIN_LOWER_CASE) && !password.matches("(.*[a-z].*)")){return false;}//检测包含大写字母if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_CONTAIN_UPPER_CASE) && !password.matches("(.*[A-Z].*)")){return false;}} else {if (!checkContainCase(password)) {return false;}}//检测包含特殊符号if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_CONTAIN_SPECIAL_CHAR) && !password.matches("(.*[`~!@#$%^&*()+=|{}':;',//[//].<>/?].*)")){return false;}//检测键盘横向连续if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_HORIZONTAL_KEY_SEQUENTIAL) && checkLateralKeyboardSite(password)){return false;}//检测键盘斜向连续if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_SLOPE_KEY_SEQUENTIAL) && checkKeyboardSlantSite(password)){return false;}//检测逻辑位置连续if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_LOGIC_SEQUENTIAL) && checkSequentialChars(password)){return false;}//检测相邻字符是否相同if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_SEQUENTIAL_CHAR_SAME) && checkSequentialSameChars(password)){return false;}return true;}public static boolean checkPasswordForUpdate(String password) {if (password == null || "".equals(password)) return false;if (!checkPasswordLength(password, "", "8")) return false;if (!password.matches("(.*[0-9].*)")) return false;if (!password.matches("(.*[a-z].*)")) return false;if (!password.matches("(.*[A-Z].*)")) return false;return true;}public static boolean checkCustomPasswordArray(String password) {Iterator iterator = PasswordConfigBean.CUSTOM_PASSWORD_ARRAY.iterator();while(iterator.hasNext()) {if(password.equals(iterator.next())) {return true;}}return false;}public static boolean checkPasswordLength(String password, String max, String min) {boolean flag = false;if("".equals(max)) {if (password.length() >= Integer.parseInt(min)) {flag = true;}} else {if (password.length() >= Integer.parseInt(min) && password.length() <= Integer.parseInt(max)) {flag = true;}}return flag;}public static boolean checkContainDigit(String password) {boolean flag = false;char[] charArray = password.toCharArray();int numberCount = 0;for (char c : charArray) {if (Character.isDigit(c)) numberCount++;}if (numberCount >= 1) flag = true;return flag;}public static boolean checkContainCase(String password) {boolean flag = false;char[] charArray = password.toCharArray();int charCount = 0;for (char c : charArray) {if (Character.isLetter(c)) charCount++;}if (charCount >= 1) flag = true;return flag;}public static boolean checkContainLowerCase(String password) {boolean flag = false;char[] charArray = password.toCharArray();int charCount = 0;for (char c : charArray) {if (Character.isLowerCase(c)) charCount++;}if (charCount >= 1) flag = true;return flag;}public static boolean checkContainUpperCase(String password) {boolean flag = false;char[] charArray = password.toCharArray();int charCount = 0;for (char c : charArray) {if (Character.isUpperCase(c)) charCount++;}if (charCount >= 1) flag = true;return flag;}public static boolean checkContainSpecialChar(String password) {boolean flag = false;char[] charArray = password.toCharArray();int specialCount = 0;for (char c : charArray) {if (PasswordConfigBean.DEFAULT_SPECIAL_CHAR.indexOf(c) != -1) specialCount++;}if (specialCount >= 1) flag = true;return flag;}public static boolean checkLateralKeyboardSite(String password) {//将所有输入字符转为小写String lowerCasePassword = password.toLowerCase();//键盘横向规则检测int arrLength = PasswordConfigBean.KEYBOARD_HORIZONTAL_ARR.length;int limitNumKey = Integer.parseInt(PasswordConfigBean.LIMIT_HORIZONTAL_KEY_NUMBER) ;for (int i = 0; i + limitNumKey <= lowerCasePassword.length(); i++) {String str = lowerCasePassword.substring(i, i+limitNumKey);String distinguishStr = password.substring(i, i+limitNumKey);String revOrderStr = null;for (int j = 0; j < arrLength; j++) {String configStr = PasswordConfigBean.KEYBOARD_HORIZONTAL_ARR[j];revOrderStr = new StringBuffer(PasswordConfigBean.KEYBOARD_HORIZONTAL_ARR[j]).reverse().toString();//检测包含字母(区分大小写)if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_CONTAIN_UPPER_LOWER_CASE)) {//考虑 大写键盘匹配的情况String UpperStr = PasswordConfigBean.KEYBOARD_HORIZONTAL_ARR[j].toUpperCase();if(configStr.contains(distinguishStr) || UpperStr.contains(distinguishStr)) {return true;}//考虑逆序输入情况下 连续输入String revUpperStr = new StringBuffer(UpperStr).reverse().toString();if(revOrderStr.contains(distinguishStr) || revUpperStr.contains(distinguishStr)) {return true;}} else {if(configStr.contains(str)) return true;//考虑逆序输入情况下 连续输入if(revOrderStr.contains(str)) return true;}}}return false;}public static boolean checkKeyboardSlantSite(String password) {//将所有输入字符转为小写String lowerCasePassword = password.toLowerCase();//键盘斜线方向规则检测int arrLength = PasswordConfigBean.KEYBOARD_SLOPE_ARR.length;int limitNumKey = Integer.parseInt(PasswordConfigBean.LIMIT_SLOPE_KEY_NUMBER);for (int i = 0; i + limitNumKey <= lowerCasePassword.length(); i++) {String str = lowerCasePassword.substring(i, i + limitNumKey);String distinguishStr = password.substring(i, i + limitNumKey);String revOrderStr = null;for (int j = 0; j < arrLength; j++) {String configStr = PasswordConfigBean.KEYBOARD_SLOPE_ARR[j];revOrderStr = new StringBuffer(PasswordConfigBean.KEYBOARD_SLOPE_ARR[j]).reverse().toString();//检测包含字母(区分大小写)if (PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_CONTAIN_UPPER_LOWER_CASE)) {//考虑 大写键盘匹配的情况String UpperStr = PasswordConfigBean.KEYBOARD_SLOPE_ARR[j].toUpperCase();if(configStr.contains(distinguishStr) || UpperStr.contains(distinguishStr)) {return true;}//考虑逆序输入情况下 连续输入String revUpperStr = new StringBuffer(UpperStr).reverse().toString();if(revOrderStr.contains(distinguishStr) || revUpperStr.contains(distinguishStr)) {return true;}} else {if(configStr.contains(str)) return true;//考虑逆序输入情况下 连续输入if(revOrderStr.contains(str)) return true;}}}return false;}public static boolean checkSequentialChars(String password) {int limitNumber = Integer.parseInt(PasswordConfigBean.LIMIT_LOGIC_NUMBER);int normalCount,reversedCount;//检测包含字母(区分大小写)if (!PasswordConfigBean.PASS_WORD_STATUS_TRUE.equals(PasswordConfigBean.CHECK_CONTAIN_UPPER_LOWER_CASE)) {password = password.toLowerCase();}char[] passwordArray = password.toCharArray();for (int i = 0; i + limitNumber <= password.length(); i++) {normalCount = 0;reversedCount = 0;for (int j = 0; j < limitNumber - 1; j++) {if (passwordArray[i + j + 1] - passwordArray[i + j] == 1) {normalCount++;if(normalCount == limitNumber - 1){return true;}}if (passwordArray[i + j] - passwordArray[i + j + 1] == 1) {reversedCount++;if(reversedCount == limitNumber - 1){return true;}}}}return false;}public static boolean checkSequentialSameChars(String password) {char[] passwordArray = password.toCharArray();int limitNumber = Integer.parseInt(PasswordConfigBean.LIMIT_SEQUENTIAL_CHAR_NUMBER);int count;for (int i = 0; i + limitNumber <= password.length(); i++) {count = 0;for (int j = 0; j < limitNumber - 1; j++) {if(passwordArray[i + j] == passwordArray[i + j + 1]) {count++;if (count == limitNumber - 1){return true;}}}}return false;}
}

3 : 验证

需要注意的是,配置文件交给Spring管理的,所以验证时,需要将项目启动。

public static void main(String[] args) {Boolean check = checkPassword("123");System.out.print(check);
}

JAVA集成强密码校验

4 : 相关链接

Springboot基于BCrypt非对称加密字符串:https://blog.csdn.net/qq_38254635/article/details/129746320
SpringBoot加载自定义yml中的配置参数:https://blog.csdn.net/qq_38254635/article/details/112033193

OK,整理到这吧!

如有不正确之处,还望指正!书写不易,觉得有帮助就点个赞吧!☺☺☺