用户登录问题修改
This commit is contained in:
parent
74373883ca
commit
12bd9c20c3
|
|
@ -51,11 +51,11 @@ public class PasswordValidatorService {
|
||||||
return AjaxResult.error("密码包含常见的弱密码片段!");
|
return AjaxResult.error("密码包含常见的弱密码片段!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (containsConsecutiveCharacters(newPassword, config.getMaxConsecutiveChars())) {
|
if (containsConsecutiveCharacters(newPassword.toLowerCase(), config.getMaxConsecutiveChars())) {
|
||||||
return AjaxResult.error("密码不能包含超过" + config.getMaxConsecutiveChars() + "位连续字符!");
|
return AjaxResult.error("密码不能包含超过" + config.getMaxConsecutiveChars() + "个连续相同字符、连续递增/递减的数字或字母(不区分大小写)");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newPassword.contains(username)) {
|
if (newPassword.toLowerCase().contains(username.toLowerCase())) {
|
||||||
return AjaxResult.error("密码不能包含账号!");
|
return AjaxResult.error("密码不能包含账号!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -120,7 +120,7 @@ public class PasswordValidatorService {
|
||||||
*/
|
*/
|
||||||
private boolean containsWeakPassword(String password) {
|
private boolean containsWeakPassword(String password) {
|
||||||
for (String weakPwd : config.getWeakPasswords()) {
|
for (String weakPwd : config.getWeakPasswords()) {
|
||||||
if (password.contains(weakPwd)) {
|
if (password.toLowerCase().contains(weakPwd)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -128,24 +128,83 @@ public class PasswordValidatorService {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查密码中是否包含超过 n 个连续相同字符
|
* 检查密码中是否包含超过 n 个连续相同字符、连续递增/递减的数字或字母(不区分大小写)
|
||||||
*/
|
*/
|
||||||
private boolean containsConsecutiveCharacters(String password, int n) {
|
private boolean containsConsecutiveCharacters(String password, int n) {
|
||||||
|
// 检查连续相同字符
|
||||||
|
n = n + 1;
|
||||||
for (int i = 0; i <= password.length() - n; i++) {
|
for (int i = 0; i <= password.length() - n; i++) {
|
||||||
boolean consecutive = true;
|
boolean consecutiveSameChar = true;
|
||||||
for (int j = 1; j < n; j++) {
|
for (int j = 1; j < n; j++) {
|
||||||
if (password.charAt(i + j) != password.charAt(i)) {
|
if (password.charAt(i + j) != password.charAt(i)) {
|
||||||
consecutive = false;
|
consecutiveSameChar = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (consecutive) {
|
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 true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 不包含连续相同字符、数字或字母序列
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 验证登录参数
|
* 验证登录参数
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -14,11 +14,10 @@ import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
|
||||||
* 密码校验器类,用于根据配置对用户输入的密码进行验证。
|
|
||||||
*/
|
|
||||||
@Service
|
@Service
|
||||||
public class PasswordValidatorServiceImpl implements PasswordValidatorService {
|
public class PasswordValidatorServiceImpl implements PasswordValidatorService {
|
||||||
|
|
||||||
|
|
@ -31,195 +30,233 @@ public class PasswordValidatorServiceImpl implements PasswordValidatorService {
|
||||||
@Resource
|
@Resource
|
||||||
private PasswordValidatorMapper passwordValidatorMapper;
|
private PasswordValidatorMapper passwordValidatorMapper;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult validatePassword(Long userId, String username, String oldPassword, String newPassword) {
|
public AjaxResult validatePassword(Long userId, String username, String oldPassword, String newPassword) {
|
||||||
// 1. 检查密码长度是否符合配置
|
// 1. 检查密码长度
|
||||||
if (newPassword.length() < config.getMinLength() || newPassword.length() > config.getMaxLength()) {
|
if (!isPasswordLengthValid(newPassword)) {
|
||||||
return AjaxResult.error("密码长度应为" + config.getMinLength() + "至" + config.getMaxLength() + "位!");
|
return AjaxResult.error("密码长度应为" + config.getMinLength() + "至" + config.getMaxLength() + "位!");
|
||||||
}
|
}
|
||||||
// 2. 检查密码是否包含大写字母、小写字母、数字和特殊字符
|
|
||||||
boolean hasUpperCase = false, hasLowerCase = false, hasDigit = false, hasSpecialChar = false;
|
// 2. 检查密码字符类型
|
||||||
for (char c : newPassword.toCharArray()) {
|
if (!isPasswordCharacterValid(newPassword)) {
|
||||||
if (Character.isUpperCase(c)) {
|
return AjaxResult.error(getCharacterRequirementErrorMessage());
|
||||||
hasUpperCase = true;
|
|
||||||
}
|
|
||||||
if (Character.isLowerCase(c)) {
|
|
||||||
hasLowerCase = true;
|
|
||||||
}
|
|
||||||
if (Character.isDigit(c)) {
|
|
||||||
hasDigit = true;
|
|
||||||
}
|
|
||||||
if ("!@#$%^&*()-_=+[{]};:'\",<.>/?".indexOf(c) >= 0) {
|
|
||||||
hasSpecialChar = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据配置检查大写字母、小写字母、数字和特殊字符的要求
|
// 3. 检查常见弱密码
|
||||||
if (config.isRequireUpperCase() && !hasUpperCase) {
|
if (containsWeakPassword(newPassword.toLowerCase())) {
|
||||||
return AjaxResult.error("密码必须包含大写字母!");
|
return AjaxResult.error("密码包含常见的弱密码片段!");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.isRequireLowerCase() && !hasLowerCase) {
|
// 4. 检查连续字符
|
||||||
return AjaxResult.error("密码必须包含小写字母!");
|
if (config.isRestrictConsecutiveChars() && containsConsecutiveCharacters(newPassword.toLowerCase(), config.getMaxConsecutiveChars())) {
|
||||||
}
|
|
||||||
|
|
||||||
if (config.isRequireDigit() && !hasDigit) {
|
|
||||||
return AjaxResult.error("密码必须包含数字!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (config.isRequireSpecialChar() && !hasSpecialChar) {
|
|
||||||
return AjaxResult.error("密码必须包含特殊字符!");
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. 检查是否包含常见弱密码
|
|
||||||
for (String weakPwd : config.getWeakPasswords()) {
|
|
||||||
if (newPassword.contains(weakPwd)) {
|
|
||||||
return AjaxResult.error("密码包含常见的弱密码片段: " + weakPwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. 检查是否包含超过规定数量的连续字符
|
|
||||||
if (config.isRestrictConsecutiveChars() && containsConsecutiveCharacters(newPassword, config.getMaxConsecutiveChars())) {
|
|
||||||
return AjaxResult.error("密码不能包含超过" + config.getMaxConsecutiveChars() + "位连续字符!");
|
return AjaxResult.error("密码不能包含超过" + config.getMaxConsecutiveChars() + "位连续字符!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 5. 检查密码中是否包含用户名
|
// 5. 检查用户名
|
||||||
if (config.isExcludeUsernameInPassword() && newPassword.contains(username)) {
|
if (config.isExcludeUsernameInPassword() && newPassword.toLowerCase().contains(username.toLowerCase())) {
|
||||||
return AjaxResult.error("密码不能包含账号!");
|
return AjaxResult.error("密码不能包含账号!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 6. 检查新密码是否与旧密码相同
|
// 6. 检查新旧密码是否相同
|
||||||
if (SecurityUtils.matchesPassword(newPassword, oldPassword)) {
|
if (SecurityUtils.matchesPassword(newPassword, oldPassword)) {
|
||||||
return AjaxResult.error("新密码不能与原密码相同!");
|
return AjaxResult.error("新密码不能与原密码相同!");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 7. 检查新密码是否与历史密码相同
|
// 7. 检查密码历史
|
||||||
List<UserPasswordHistory> userPasswordHistories = passwordValidatorMapper.checkPasswordExpiry(userId);
|
if (isPasswordInHistory(userId, newPassword)) {
|
||||||
// 如果没有找到密码历史记录,返回提示
|
return AjaxResult.error("新密码不能与最近的" + config.getPasswordHistoryLimit() + "个旧密码相同!");
|
||||||
if (userPasswordHistories.isEmpty()) {
|
|
||||||
return AjaxResult.success("没有找到密码历史记录。");
|
|
||||||
}
|
|
||||||
// 只取最近的五次修改记录
|
|
||||||
// 使用 Math.min 以确保不会超过实际记录数
|
|
||||||
int limit = Math.min(userPasswordHistories.size(), config.getPasswordHistoryLimit());
|
|
||||||
for (int i = 0; i < limit; i++) {
|
|
||||||
UserPasswordHistory history = userPasswordHistories.get(i);
|
|
||||||
// 比较新密码与历史密码
|
|
||||||
if (SecurityUtils.matchesPassword(newPassword, history.getNewPassword())) {
|
|
||||||
return AjaxResult.error("新密码不能与最近的" + config.getPasswordHistoryLimit() + "个旧密码相同!");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return AjaxResult.success();
|
return AjaxResult.success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isPasswordLengthValid(String password) {
|
||||||
|
return password.length() >= config.getMinLength() && password.length() <= config.getMaxLength();
|
||||||
|
}
|
||||||
|
|
||||||
|
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 (config.isRequireUpperCase() && !hasUpperCase) return false;
|
||||||
|
if (config.isRequireLowerCase() && !hasLowerCase) return false;
|
||||||
|
if (config.isRequireDigit() && !hasDigit) return false;
|
||||||
|
return !(config.isRequireSpecialChar() && !hasSpecialChar);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean containsWeakPassword(String password) {
|
||||||
|
Set<String> weakPasswords = new HashSet<>(config.getWeakPasswords());
|
||||||
|
for (String weakPwd : weakPasswords) {
|
||||||
|
if (password.contains(weakPwd)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 检查用户是否是首次登录
|
* 根据配置返回密码不符合要求时的错误提示信息
|
||||||
*
|
|
||||||
* @return 如果密码符合策略要求,则返回 true,否则返回 false
|
|
||||||
*/
|
*/
|
||||||
|
private String getCharacterRequirementErrorMessage() {
|
||||||
|
if (config.isRequireUpperCase()) {
|
||||||
|
return "密码必须包含大写字母!";
|
||||||
|
}
|
||||||
|
if (config.isRequireLowerCase()) {
|
||||||
|
return "密码必须包含小写字母!";
|
||||||
|
}
|
||||||
|
if (config.isRequireDigit()) {
|
||||||
|
return "密码必须包含数字!";
|
||||||
|
}
|
||||||
|
if (config.isRequireSpecialChar()) {
|
||||||
|
return "密码必须包含特殊字符!";
|
||||||
|
}
|
||||||
|
return "密码不符合字符要求!";
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isPasswordInHistory(Long userId, String newPassword) {
|
||||||
|
List<UserPasswordHistory> userPasswordHistories = passwordValidatorMapper.checkPasswordExpiry(userId);
|
||||||
|
if (userPasswordHistories.isEmpty()) return false;
|
||||||
|
|
||||||
|
// 只取最近的五次修改记录
|
||||||
|
int limit = Math.min(userPasswordHistories.size(), config.getPasswordHistoryLimit());
|
||||||
|
for (int i = 0; i < limit; i++) {
|
||||||
|
UserPasswordHistory history = userPasswordHistories.get(i);
|
||||||
|
if (SecurityUtils.matchesPassword(newPassword, history.getNewPassword())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkFirstLogin() {
|
public boolean checkFirstLogin() {
|
||||||
// 如果未开启首次登录强制修改密码功能,直接返回错误
|
|
||||||
if (!config.isForcePasswordChangeOnFirstLogin()) {
|
if (!config.isForcePasswordChangeOnFirstLogin()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||||
SysUser sysUser = loginUser.getSysUser();
|
SysUser sysUser = loginUser.getSysUser();
|
||||||
// 获取初始密码配置
|
|
||||||
String initialPassword = configService.selectConfigByKey("sys.user.initPassword");
|
String initialPassword = configService.selectConfigByKey("sys.user.initPassword");
|
||||||
// 检查当前用户密码是否是初始密码
|
|
||||||
// 根据检查结果返回相应的响应
|
|
||||||
return SecurityUtils.matchesPassword(initialPassword, sysUser.getPassword());
|
return SecurityUtils.matchesPassword(initialPassword, sysUser.getPassword());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查用户密码是否已过期,提示用户定期修改密码。
|
|
||||||
*
|
|
||||||
* @return 如果需要修改密码,返回 AjaxResult 提示用户修改,否则返回成功信息
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public boolean checkPasswordExpiry() {
|
public boolean checkPasswordExpiry() {
|
||||||
Long userId = SecurityUtils.getUserId();
|
Long userId = SecurityUtils.getUserId();
|
||||||
List<UserPasswordHistory> userPasswordHistories = passwordValidatorMapper.checkPasswordExpiry(userId);
|
List<UserPasswordHistory> userPasswordHistories = passwordValidatorMapper.checkPasswordExpiry(userId);
|
||||||
// 如果没有找到密码历史记录,返回错误
|
|
||||||
if (userPasswordHistories.isEmpty()) {
|
if (userPasswordHistories.isEmpty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// 获取最近的密码修改记录
|
|
||||||
UserPasswordHistory userPasswordHistory = userPasswordHistories.get(0);
|
UserPasswordHistory userPasswordHistory = userPasswordHistories.get(0);
|
||||||
// 获取当前日期
|
|
||||||
Date currentDate = DateUtils.getNowDate();
|
Date currentDate = DateUtils.getNowDate();
|
||||||
// 获取最近密码修改日期
|
|
||||||
Date changeDate = DateUtils.toDate(userPasswordHistory.getChangeTimestamp());
|
Date changeDate = DateUtils.toDate(userPasswordHistory.getChangeTimestamp());
|
||||||
|
|
||||||
// 计算最近密码修改到当前日期的天数
|
|
||||||
long daysSinceChange = DateUtils.daysBetween(changeDate, currentDate);
|
long daysSinceChange = DateUtils.daysBetween(changeDate, currentDate);
|
||||||
// 检查是否达到定期修改密码的天数要求
|
|
||||||
return daysSinceChange > config.getRegularlyChangePassword();
|
return daysSinceChange > config.getRegularlyChangePassword();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 检查新密码是否在最近五次修改的密码中
|
|
||||||
*
|
|
||||||
* @param userId 用户ID
|
|
||||||
* @param newPassword 新密码
|
|
||||||
* @return 如果新密码在最近的五次修改记录中,返回错误提示,否则返回成功提示
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public AjaxResult isPasswordInRecentHistory(Long userId, String newPassword) {
|
public AjaxResult isPasswordInRecentHistory(Long userId, String newPassword) {
|
||||||
List<UserPasswordHistory> userPasswordHistories = passwordValidatorMapper.checkPasswordExpiry(userId);
|
List<UserPasswordHistory> userPasswordHistories = passwordValidatorMapper.checkPasswordExpiry(userId);
|
||||||
|
|
||||||
// 如果没有找到密码历史记录,返回提示
|
|
||||||
if (userPasswordHistories.isEmpty()) {
|
if (userPasswordHistories.isEmpty()) {
|
||||||
return AjaxResult.success("没有找到密码历史记录。");
|
return AjaxResult.success("没有找到密码历史记录。");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 只取最近的五次修改记录
|
|
||||||
// 使用 Math.min 以确保不会超过实际记录数
|
|
||||||
int limit = Math.min(userPasswordHistories.size(), config.getPasswordHistoryLimit());
|
int limit = Math.min(userPasswordHistories.size(), config.getPasswordHistoryLimit());
|
||||||
for (int i = 0; i < limit; i++) {
|
for (int i = 0; i < limit; i++) {
|
||||||
UserPasswordHistory history = userPasswordHistories.get(i);
|
UserPasswordHistory history = userPasswordHistories.get(i);
|
||||||
// 比较新密码与历史密码
|
|
||||||
if (SecurityUtils.matchesPassword(newPassword, history.getNewPassword())) {
|
if (SecurityUtils.matchesPassword(newPassword, history.getNewPassword())) {
|
||||||
return AjaxResult.error("新密码不能与最近的密码相同。"); // 新密码在最近五次记录中
|
return AjaxResult.error("新密码不能与最近的密码相同。");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return AjaxResult.success("新密码有效。"); // 新密码不在记录中
|
return AjaxResult.success("新密码有效。");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param userPasswordHistory
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public int addPasswordExpiry(UserPasswordHistory userPasswordHistory) {
|
public int addPasswordExpiry(UserPasswordHistory userPasswordHistory) {
|
||||||
return passwordValidatorMapper.addPasswordExpiry(userPasswordHistory);
|
return passwordValidatorMapper.addPasswordExpiry(userPasswordHistory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 帮助方法,用于检测密码是否包含超过 n 个连续相同字符。
|
* 检查密码中是否包含超过 n 个连续相同字符、连续递增/递减的数字或字母(不区分大小写)
|
||||||
*
|
|
||||||
* @param password 需要检查的密码
|
|
||||||
* @param n 允许的最大连续相同字符数量
|
|
||||||
* @return 如果包含连续字符,则返回 true,否则返回 false
|
|
||||||
*/
|
*/
|
||||||
private boolean containsConsecutiveCharacters(String password, int n) {
|
private boolean containsConsecutiveCharacters(String password, int n) {
|
||||||
|
// 检查连续相同字符
|
||||||
|
n = n + 1;
|
||||||
for (int i = 0; i <= password.length() - n; i++) {
|
for (int i = 0; i <= password.length() - n; i++) {
|
||||||
boolean consecutive = true;
|
boolean consecutiveSameChar = true;
|
||||||
for (int j = 1; j < n; j++) {
|
for (int j = 1; j < n; j++) {
|
||||||
if (password.charAt(i + j) != password.charAt(i)) {
|
if (password.charAt(i + j) != password.charAt(i)) {
|
||||||
consecutive = false;
|
consecutiveSameChar = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (consecutive) {
|
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 true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 不包含连续相同字符、数字或字母序列
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue