diff --git a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/customer/service/impl/CustInfoServiceImpl.java b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/customer/service/impl/CustInfoServiceImpl.java index 5036f75e..d66a2c5d 100644 --- a/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/customer/service/impl/CustInfoServiceImpl.java +++ b/bonus-modules/bonus-smart-canteen/src/main/java/com/bonus/canteen/core/customer/service/impl/CustInfoServiceImpl.java @@ -50,6 +50,7 @@ import com.bonus.common.houqin.domain.SmsCodeVerifyDTO; import com.bonus.common.houqin.utils.AesEncryptUtil; import com.bonus.common.houqin.utils.LeBeanUtil; import com.bonus.common.houqin.utils.id.Id; +import com.bonus.common.security.utils.SecurityUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -205,6 +206,10 @@ public class CustInfoServiceImpl extends ServiceImpl i content.setNewPassword(AesEncryptUtil.aesDecode(content.getNewPassword())); String oldPassword = content.getOldPassword(); String newPassword = content.getNewPassword(); + AjaxResult pwdCheckResult = validatePassword(oldPassword, newPassword); + if (ajaxResult.isError()) { + return pwdCheckResult; + } if (Objects.equals(oldPassword, newPassword)) { log.error("小程序修改密码错误:两次密码不能一致"); ajaxResult.put("msg", "小程序修改密码错误:两次密码不能一致"); @@ -230,11 +235,192 @@ public class CustInfoServiceImpl extends ServiceImpl i return ajaxResult; } -// public static void main(String[] args) { -// BCryptPasswordEncoder bCrypt = new BCryptPasswordEncoder(); -// boolean flag = bCrypt.matches("Bonus$2026", "$2a$10$vrcmG0TyvgH5tS9g8ptaVOK2K3pYWVAa13SWEK7pQBGRtNAPlGV7O"); -// System.out.println(flag); -// } + public AjaxResult validatePassword(String oldPassword, String newPassword) { + // 1. 检查密码长度 + if (!isPasswordLengthValid(newPassword)) { + return AjaxResult.error("密码长度应为6至16位!"); + } + + // 2. 检查密码字符类型 + if (!isPasswordCharacterValid(newPassword)) { + return AjaxResult.error("密码不符合字符要求!"); + } + + // 3. 检查常见弱密码 + if (containsWeakPassword(newPassword.toLowerCase())) { + return AjaxResult.error("密码包含常见的弱密码片段!"); + } + + // 4. 检查连续字符 + if (containsConsecutiveCharacters(newPassword.toLowerCase(), 3)) { + return AjaxResult.error("密码不能包含超过3位连续字符!"); + } + + // 5. 检查新旧密码是否相同 + if (SecurityUtils.matchesPassword(newPassword, oldPassword)) { + return AjaxResult.error("新密码不能与原密码相同!"); + } + + return AjaxResult.success(); + } + + private boolean isPasswordLengthValid(String password) { + return password.length() >= 6 && password.length() <= 16; + } + + private boolean isPasswordCharacterValid(String password) { + boolean hasUpperCase = false, hasLowerCase = false, hasDigit = false, hasSpecialChar = false; + + for (char c : password.toCharArray()) { + if (Character.isUpperCase(c)) { + hasUpperCase = true; + } + if (Character.isLowerCase(c)) { + hasLowerCase = true; + } + if (Character.isDigit(c)) { + hasDigit = true; + } + if ("!@#$%^&*()-_=+[{]};:'\",<.>/?".indexOf(c) >= 0) { + hasSpecialChar = true; + } + } + + if (!hasUpperCase) { + return false; + } + if (!hasLowerCase) { + return false; + } + if (!hasDigit) { + return false; + } + return !(true && !hasSpecialChar); + } + + private boolean containsWeakPassword(String password) { + Set weakPasswords = new HashSet<>(Arrays.asList("111", + "888", + "123", + "234", + "345", + "456", + "567", + "678", + "789", + "1234", + "2345", + "3456", + "4567", + "5678", + "6789", + "abc", + "abcd", + "abcde", + "abcdef", + "abcdefg", + "qwe", + "qwer", + "qwert", + "qwerty", + "asdf", + "asdfg", + "asdfgh", + "password", + "passw0rd", + "letmein", + "welcome", + "admin", + "user", + "test", + "pass", + "root", + "login")); + for (String weakPwd : weakPasswords) { + if (password.contains(weakPwd)) { + return true; + } + } + return false; + } + + /** + * 检查密码中是否包含超过 n 个连续相同字符、连续递增/递减的数字或字母(不区分大小写) + */ + private boolean containsConsecutiveCharacters(String password, int n) { + // 检查连续相同字符 + n = n + 1; + for (int i = 0; i <= password.length() - n; i++) { + boolean consecutiveSameChar = true; + for (int j = 1; j < n; j++) { + if (password.charAt(i + j) != password.charAt(i)) { + consecutiveSameChar = false; + break; + } + } + if (consecutiveSameChar) { + return true; // 包含超过 n 个连续相同字符 + } + } + + // 检查连续递增或递减的数字 + for (int i = 0; i <= password.length() - n; i++) { + boolean consecutiveIncreasing = true; + boolean consecutiveDecreasing = true; + for (int j = 1; j < n; j++) { + char currentChar = password.charAt(i); + char nextChar = password.charAt(i + j); + + // 检查数字递增或递减 + if (Character.isDigit(currentChar) && Character.isDigit(nextChar)) { + if (nextChar != currentChar + j) { + consecutiveIncreasing = false; + } + if (nextChar != currentChar - j) { + consecutiveDecreasing = false; + } + } else { + consecutiveIncreasing = false; + consecutiveDecreasing = false; + break; + } + } + if (consecutiveIncreasing || consecutiveDecreasing) { + return true; // 包含超过 n 个递增或递减的连续数字 + } + } + + // 检查连续递增或递减的字母(不区分大小写) + for (int i = 0; i <= password.length() - n; i++) { + boolean consecutiveIncreasing = true; + boolean consecutiveDecreasing = true; + for (int j = 1; j < n; j++) { + char currentChar = Character.toLowerCase(password.charAt(i)); // 转为小写 + char nextChar = Character.toLowerCase(password.charAt(i + j)); // 转为小写 + + // 检查字母递增或递减 + if (Character.isLetter(currentChar) && Character.isLetter(nextChar)) { + if (nextChar != currentChar + j) { + consecutiveIncreasing = false; + } + if (nextChar != currentChar - j) { + consecutiveDecreasing = false; + } + } else { + consecutiveIncreasing = false; + consecutiveDecreasing = false; + break; + } + } + if (consecutiveIncreasing || consecutiveDecreasing) { + // 包含超过 n 个递增或递减的连续字母 + return true; + } + } + // 不包含连续相同字符、数字或字母序列 + return false; + } + @Override public AjaxResult custForgetPassword(CustForgetPasswordDTO content) {