需求修改及优化

This commit is contained in:
mashuai 2025-04-22 11:00:41 +08:00
parent 16af2a6323
commit f1ccc8f38e
19 changed files with 557 additions and 28 deletions

View File

@ -1,6 +1,6 @@
package com.bonus.sgzb.system.api;
import com.bonus.sgzb.common.core.web.domain.AjaxResult;
import com.bonus.sgzb.common.core.domain.UserPasswordHistory;
import com.bonus.sgzb.system.api.domain.SysUser;
import com.bonus.sgzb.system.api.domain.UrgentProcessingUser;
import com.bonus.sgzb.system.api.factory.RemoteUserFallbackFactory;
@ -95,4 +95,12 @@ public interface RemoteUserService
*/
@PostMapping("/user/processingUser")
public R<List<SysUser>> processingUser(@RequestBody UrgentProcessingUser urgentProcessingUser);
/**
* 获取用户密码历史信息
* @param passwordHistory
* @return
*/
@PostMapping("/user/checkPasswordExpiry")
public R<List<UserPasswordHistory>> checkPasswordExpiry(UserPasswordHistory passwordHistory);
}

View File

@ -28,6 +28,19 @@ public class SysUser extends BaseEntity
@Excel(name = "用户序号", cellType = ColumnType.NUMERIC, prompt = "用户编号")
private Long userId;
/**
* 变更人
*/
private Long changeUser;
public Long getChangeUser() {
return changeUser;
}
public void setChangeUser(Long changeUser) {
this.changeUser = changeUser;
}
/** 部门ID */
@Excel(name = "部门编号", type = Type.IMPORT)
private Long deptId;
@ -80,6 +93,17 @@ public class SysUser extends BaseEntity
/** 密码 */
private String password;
/** 老密码 */
private String oldPassword;
public String getOldPassword() {
return oldPassword;
}
public void setOldPassword(String oldPassword) {
this.oldPassword = oldPassword;
}
/** 帐号状态0正常 1停用 */
@Excel(name = "帐号状态", readConverterExp = "0=正常,1=停用")
private String status;

View File

@ -1,6 +1,6 @@
package com.bonus.sgzb.system.api.factory;
import com.bonus.sgzb.common.core.web.domain.AjaxResult;
import com.bonus.sgzb.common.core.domain.UserPasswordHistory;
import com.bonus.sgzb.system.api.domain.UrgentProcessingUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -10,12 +10,9 @@ import com.bonus.sgzb.common.core.domain.R;
import com.bonus.sgzb.system.api.RemoteUserService;
import com.bonus.sgzb.system.api.domain.SysUser;
import com.bonus.sgzb.system.api.model.LoginUser;
import org.springframework.web.bind.annotation.RequestBody;
import java.util.List;
import static com.bonus.sgzb.common.core.web.domain.AjaxResult.success;
/**
* 用户服务降级处理
*
@ -71,6 +68,11 @@ public class RemoteUserFallbackFactory implements FallbackFactory<RemoteUserServ
public R<List<SysUser>> processingUser(UrgentProcessingUser urgentProcessingUser){
return R.fail("获取用户失败:" + throwable.getMessage());
}
@Override
public R<List<UserPasswordHistory>> checkPasswordExpiry(UserPasswordHistory passwordHistory){
return R.fail("获取用户失败:" + throwable.getMessage());
}
};
}
}

View File

@ -82,6 +82,29 @@ public class TokenController {
}
}
/**
* 检查密码状态
* @param form
* @return
*/
@PostMapping("/checkPasswordStatus")
public AjaxResult checkPasswordStatus(@RequestBody LoginBody form) throws Exception {
String decryptedData = RsaUtil.decryptByPrivateKey(form.getPassword(), privateKey);
// 1. 先检查是否是首次登录
boolean firstLoginResult = sysLoginService.checkFirstLogin(form.getUsername(), decryptedData);
if (firstLoginResult) {
return AjaxResult.success("首次登录需要修改密码", true);
}
// 2. 再检查密码是否已过期
boolean passwordExpiryResult = sysLoginService.checkPasswordExpiry(form.getUsername(), decryptedData);
// 如果密码已过期返回密码过期的提示
if (passwordExpiryResult) {
return AjaxResult.success("登录密码已过60天有效期请修改密码后重新登录", true);
}
// 3. 如果都不需要操作返回成功
return AjaxResult.success(false);
}
/**
* App端登录
* @param form

View File

@ -92,11 +92,6 @@ public class SysLoginService {
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "用户已停用,请联系管理员");
throw new ServiceException("对不起,您的账号:" + username + " 已停用");
}
// 判断密码是否为原始密码原始密码需要修改密码方可登录
/*if (passwordService.checkFirstLogin(user, password)) {
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录密码为系统默认密码,请修改密码后重新登录");
throw new ServiceException("登录密码为系统默认密码,请修改密码后重新登录");
}*/
passwordService.validate(user, password);
recordLogService.recordLogininfor(username, Constants.LOGIN_SUCCESS, "登录成功");
return userInfo;
@ -287,4 +282,38 @@ public class SysLoginService {
}
return password.toString();
}
/**
* 判断是否第一次登录
* @param username
* @param password
* @return
*/
public boolean checkFirstLogin(String username, String password) {
// 判断密码是否为原始密码原始密码需要修改密码方可登录
if ("NxCc@2024*".equals(password)) {
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录密码为系统默认密码,请修改密码后重新登录");
return true;
}
return false;
}
/**
* 检查密码是否过期
* @param username
* @param password
* @return
*/
public boolean checkPasswordExpiry(String username, String password) {
// 查询用户信息
R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);
SysUser user = userResult.getData().getSysUser();
// 2. 再检查密码是否已过期
boolean passwordExpiryResult = passwordService.checkPasswordExpiry(user, password);
if (passwordExpiryResult) {
recordLogService.recordLogininfor(username, Constants.LOGIN_FAIL, "登录密码已过60天有效期请修改密码后重新登录");
return true;
}
return false;
}
}

View File

@ -1,8 +1,16 @@
package com.bonus.sgzb.auth.service;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import com.bonus.sgzb.auth.utils.SystemConfig;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.bonus.sgzb.common.core.domain.UserPasswordHistory;
import com.bonus.sgzb.common.core.utils.DateUtils;
import com.bonus.sgzb.common.core.utils.SystemConfig;
import com.bonus.sgzb.system.api.RemoteUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.bonus.sgzb.common.core.constant.CacheConstants;
@ -34,6 +42,9 @@ public class SysPasswordService {
@Autowired
private SysRecordLogService recordLogService;
@Resource
private RemoteUserService remoteUserService;
/**
* 登录账户密码错误次数缓存键名
*
@ -88,4 +99,41 @@ public class SysPasswordService {
}
return false;
}
/**
* 密码过期校验
* @param user
* @param password
* @return
*/
public boolean checkPasswordExpiry(SysUser user, String password) {
if (!systemConfig.getPasswordConfig().isEnableRegularlyChangePassword()) {
return false;
}
UserPasswordHistory passwordHistory = new UserPasswordHistory();
passwordHistory.setUserId(user.getUserId());
List<UserPasswordHistory> userPasswordHistories = remoteUserService.checkPasswordExpiry(passwordHistory).getData();
Date createTime = null;
if (userPasswordHistories.isEmpty()) {
createTime = user.getCreateTime();
}
LocalDateTime changeTimestamp = null;
if (!CollectionUtils.isEmpty(userPasswordHistories)) {
UserPasswordHistory userPasswordHistory = userPasswordHistories.get(0);
changeTimestamp = userPasswordHistory.getChangeTimestamp();
}
if (changeTimestamp == null && createTime != null) {
// Date 转换为 LocalDateTime
changeTimestamp = createTime.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDateTime();
}
Date currentDate = DateUtils.getNowDate();
if (changeTimestamp != null) {
Date changeDate = DateUtils.toDate(changeTimestamp);
long daysSinceChange = DateUtils.daysBetween(changeDate, currentDate);
return daysSinceChange > systemConfig.getPasswordConfig().getRegularlyChangePassword();
}
return false;
}
}

View File

@ -0,0 +1,38 @@
package com.bonus.sgzb.common.core.domain;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDateTime;
/**
* @author bonus
*/
@Data
public class UserPasswordHistory implements Serializable {
/**
* 记录的唯一标识符
*/
private Long id;
/**
* 用户的唯一标识符
*/
private Long userId;
/**
* 旧密码的哈希值
*/
private String oldPassword;
/**
* 新密码的哈希值
*/
private String newPassword;
/**
* 密码变更时间
*/
private LocalDateTime changeTimestamp;
/**
* 变更人
*/
private Long changeUser;
}

View File

@ -9,6 +9,8 @@ import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.time.DateFormatUtils;
/**
@ -180,4 +182,16 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}
/**
* 获取两个日期之间的天数
*
* @param startDate 开始日期
* @param endDate 结束日期
* @return 两个日期之间的天数
*/
public static long daysBetween(Date startDate, Date endDate) {
long diffInMillis = endDate.getTime() - startDate.getTime();
return TimeUnit.DAYS.convert(diffInMillis, TimeUnit.MILLISECONDS);
}
}

View File

@ -1,4 +1,4 @@
package com.bonus.sgzb.auth.utils;
package com.bonus.sgzb.common.core.utils;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;

View File

@ -666,7 +666,7 @@ public class PoiOutPage {
// 创建工作簿和工作表
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet();
sheet.setDefaultColumnWidth(16); // 设置列宽
sheet.setDefaultColumnWidth(30); // 设置列宽
// 创建样式
HSSFCellStyle titleStyle = createTitleStyle(workbook);
@ -703,9 +703,37 @@ public class PoiOutPage {
RegionUtil.setBorderLeft(BorderStyle.THIN, cellRange, sheet);
RegionUtil.setBorderRight(BorderStyle.THIN, cellRange, sheet);
}
rowNum = createTotalRowBack(sheet, rowNum, list, headerStyle);
return workbook;
}
/**
* 退料单导出
* @param sheet
* @param rowNum
* @param list
* @param headerStyle
* @return
*/
private static int createTotalRowBack(HSSFSheet sheet, int rowNum, List<String> list, HSSFCellStyle headerStyle) {
HSSFRow row = sheet.createRow(rowNum++);
row.setHeightInPoints(30);
sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 0, (short) (list.size() - 1)));
HSSFCell cell = row.createCell(0);
cell.setCellStyle(headerStyle);
cell.setCellValue("退料: " + " 操作人: ");
// 添加边框
CellRangeAddress cellRange = new CellRangeAddress(rowNum - 1, rowNum - 1, 0, (short) (list.size() - 1));
// 设置边框样式
RegionUtil.setBorderTop(BorderStyle.THIN, cellRange, sheet);
RegionUtil.setBorderBottom(BorderStyle.THIN, cellRange, sheet);
RegionUtil.setBorderLeft(BorderStyle.THIN, cellRange, sheet);
RegionUtil.setBorderRight(BorderStyle.THIN, cellRange, sheet);
return rowNum;
}
/**
* 退料单导出
* @param sheet
@ -763,12 +791,12 @@ public class PoiOutPage {
HSSFRow row4 = sheet.createRow(rowNum++);
row4.setHeightInPoints(30);
sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 0, 1));
HSSFCell cell7 = row3.createCell(0);
HSSFCell cell7 = row4.createCell(0);
cell7.setCellStyle(titleStyle);
cell7.setCellValue("退料时间:");
sheet.addMergedRegion(new CellRangeAddress(rowNum - 1, rowNum - 1, 2, (short) (nColumn - 1))); // projectName 占剩余的22
HSSFCell cell8 = row3.createCell(2);
HSSFCell cell8 = row4.createCell(2);
cell8.setCellStyle(titleStyle);
cell8.setCellValue(backTime);

View File

@ -1 +1,2 @@
com.bonus.sgzb.common.core.utils.SpringUtils
com.bonus.sgzb.common.core.utils.SystemConfig

View File

@ -671,7 +671,21 @@ public class TmTaskServiceImpl implements TmTaskService {
//调试经理可以查看调试设备
return tmTaskMapper.getLeaseOutListByts(task);
} else {
return tmTaskMapper.getLeaseOutListByUser(task);
List<TmTask> list = tmTaskMapper.getLeaseOutListByUser(task);
if (CollectionUtils.isNotEmpty(list)) {
for (TmTask tmTask : list) {
// 首先排除任务状态为待出库或者出库完成的状态
if (tmTask.getTaskStatus() == 33 || tmTask.getTaskStatus() == 35) {
continue;
}
if (tmTask.getPreCountNum().equals(tmTask.getAlNum())) {
// 全部出库返回个人任务状态为出库完成不修改整条任务状态
tmTask.setTaskStatus(35);
tmTask.setTaskName("完成");
}
}
}
return list;
}
}

View File

@ -1030,6 +1030,9 @@
AND (bai.agreement_code like concat('%', #{record.keyWord}, '%') or
tt.code like concat('%', #{record.keyWord}, '%'))
</if>
<if test="record.taskStatus != null and record.taskStatus != ''">
AND tt.task_status = #{record.taskStatus}
</if>
GROUP BY tt.task_id
order by
case when #{record.orderStatus} = 0 then tt.update_time

View File

@ -625,8 +625,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="agreementCode != null and agreementCode != ''">
and bagi.agreement_code like concat('%', #{agreementCode}, '%')
</if>
<if test="time != null and time != ''">
and bai.back_time =#{time}
<if test="startTime != null and startTime != '' and endTime != null and endTime != ''">
<![CDATA[and DATE_FORMAT( bai.back_time, '%Y-%m-%d' ) BETWEEN #{startTime} AND #{endTime} ]]>
</if>
<if test="backSource != null and backSource != ''">
and bai.back_source =#{backSource}
@ -1029,8 +1029,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<if test="agreementCode != null and agreementCode != ''">
and bagi.agreement_code like concat('%', #{agreementCode}, '%')
</if>
<if test="time != null and time != ''">
and DATE(bai.create_time) = #{time}
<if test="startTime != null and startTime != '' and endTime != null and endTime != ''">
<![CDATA[and DATE_FORMAT( bai.create_time, '%Y-%m-%d' ) BETWEEN #{startTime} AND #{endTime} ]]>
</if>
<if test="backSource != null and backSource != ''">
and bai.back_source =#{backSource}

View File

@ -4,6 +4,7 @@ import com.bonus.sgzb.common.core.constant.Constants;
import com.bonus.sgzb.common.core.constant.SecurityConstants;
import com.bonus.sgzb.common.core.constant.UserConstants;
import com.bonus.sgzb.common.core.domain.R;
import com.bonus.sgzb.common.core.domain.UserPasswordHistory;
import com.bonus.sgzb.common.core.exception.ServiceException;
import com.bonus.sgzb.common.core.utils.StringUtils;
import com.bonus.sgzb.common.core.utils.poi.ExcelUtil;
@ -263,13 +264,17 @@ public class SysUserController extends BaseController {
/**
* 重置密码
*/
@RequiresPermissions("system:user:edit")
//@RequiresPermissions("system:user:edit")
@Log(title = "用户管理", businessType = BusinessType.UPDATE)
@PutMapping("/resetPwd")
public AjaxResult resetPwd(@RequestBody SysUser user) throws Exception {
Long userId = SecurityUtils.getUserId();
user.setUserId(userId);
String decrypt = RsaUtil.decryptByPrivateKey(user.getPassword(), Constants.privateKey);
userService.checkUserAllowed(user);
//userService.checkUserAllowed(user);
userService.checkUserDataScope(user.getUserId());
// 检验密码规范性
userService.checkUserFirstLogin(user, decrypt);
user.setPassword(SecurityUtils.encryptPassword(decrypt));
user.setUpdateBy(SecurityUtils.getUsername());
return toAjax(userService.resetPwd(user));
@ -401,4 +406,15 @@ public class SysUserController extends BaseController {
return R.ok(userService.urgentProcessingUser(urgentProcessingUser));
}
/**
* 获取用户密码信息
* @param passwordHistory
* @return
*/
@ApiOperation(value = "获取用户历史密码信息")
@PostMapping("/checkPasswordExpiry")
public R<List<UserPasswordHistory>> checkPasswordExpiry(@RequestBody UserPasswordHistory passwordHistory) {
return R.ok(userService.checkPasswordExpiry(passwordHistory));
}
}

View File

@ -1,6 +1,8 @@
package com.bonus.sgzb.system.mapper;
import java.util.List;
import com.bonus.sgzb.common.core.domain.UserPasswordHistory;
import org.apache.ibatis.annotations.Param;
import com.bonus.sgzb.system.api.domain.SysUser;
@ -146,4 +148,18 @@ public interface SysUserMapper
String selectPickingFirst(SysUser user);
String selectRoleName(SysUser sysUser);
/**
* 插入密码历史
* @param user
* @return
*/
int insertPasswordHistory(SysUser user);
/**
* 获取密码历史
* @param passwordHistory
* @return
*/
List<UserPasswordHistory> checkPasswordExpiry(UserPasswordHistory passwordHistory);
}

View File

@ -2,7 +2,7 @@ package com.bonus.sgzb.system.service;
import java.util.List;
import com.bonus.sgzb.common.core.web.domain.AjaxResult;
import com.bonus.sgzb.common.core.domain.UserPasswordHistory;
import com.bonus.sgzb.system.api.domain.SysUser;
import com.bonus.sgzb.system.api.domain.UrgentProcessingUser;
import org.apache.ibatis.annotations.Mapper;
@ -223,4 +223,18 @@ public interface ISysUserService
* @return
*/
List<SysUser> urgentProcessingUser(UrgentProcessingUser urgentProcessingUser);
/**
* 检验密码规范性
* @param user
* @param decrypt
*/
void checkUserFirstLogin(SysUser user, String decrypt);
/**
* 获取用户历史密码信息
* @param passwordHistory
* @return
*/
List<UserPasswordHistory> checkPasswordExpiry(UserPasswordHistory passwordHistory);
}

View File

@ -1,12 +1,13 @@
package com.bonus.sgzb.system.service.impl;
import com.bonus.sgzb.common.core.constant.UserConstants;
import com.bonus.sgzb.common.core.domain.UserPasswordHistory;
import com.bonus.sgzb.common.core.enums.TaskStatusEnum;
import com.bonus.sgzb.common.core.exception.ServiceException;
import com.bonus.sgzb.common.core.utils.SpringUtils;
import com.bonus.sgzb.common.core.utils.StringUtils;
import com.bonus.sgzb.common.core.utils.SystemConfig;
import com.bonus.sgzb.common.core.utils.bean.BeanValidators;
import com.bonus.sgzb.common.core.web.domain.AjaxResult;
import com.bonus.sgzb.common.datascope.annotation.DataScope;
import com.bonus.sgzb.common.security.utils.SecurityUtils;
import com.bonus.sgzb.system.api.domain.SysDept;
@ -16,7 +17,6 @@ import com.bonus.sgzb.system.domain.SysPost;
import com.bonus.sgzb.system.domain.SysUserPost;
import com.bonus.sgzb.system.domain.SysUserRole;
import com.bonus.sgzb.system.api.domain.UrgentProcessingUser;
import com.bonus.sgzb.system.exception.SystemException;
import com.bonus.sgzb.system.mapper.*;
import com.bonus.sgzb.system.service.ISysConfigService;
import com.bonus.sgzb.system.service.ISysUserService;
@ -29,10 +29,11 @@ import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import javax.validation.Validator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
import static com.bonus.sgzb.common.core.web.domain.AjaxResult.success;
/**
* 用户 业务层处理
@ -67,6 +68,9 @@ public class SysUserServiceImpl implements ISysUserService {
@Resource
private SysDeptMapper deptMapper;
@Resource
private SystemConfig systemConfig;
/**
* 根据条件分页查询用户列表
*
@ -388,7 +392,20 @@ public class SysUserServiceImpl implements ISysUserService {
*/
@Override
public int resetPwd(SysUser user) {
return userMapper.updateUser(user);
// 根据id查询用户信息
SysUser sysUser = userMapper.selectUserById(user.getUserId());
// 往sys_user_password_history表中新增密码信息作为记录存储
user.setChangeUser(SecurityUtils.getUserId());
user.setOldPassword(sysUser.getPassword());
int result = userMapper.insertPasswordHistory(user);
if (result <= 0) {
throw new ServiceException("重置密码失败,请联系管理员");
}
result = userMapper.updateUser(user);
if (result <= 0) {
throw new ServiceException("重置密码失败,请联系管理员");
}
return result;
}
/**
@ -584,6 +601,217 @@ public class SysUserServiceImpl implements ISysUserService {
return userList;
}
/**
* 检验密码规范性
* @param user
* @param decrypt
*/
@Override
public void checkUserFirstLogin(SysUser user, String decrypt) {
// 1. 检查密码长度
if (!isPasswordLengthValid(decrypt)) {
throw new ServiceException("新密码长度应为" + systemConfig.getPasswordConfig().getMinLength() + "" + systemConfig.getPasswordConfig().getMaxLength() + "位!");
}
// 2. 检查密码字符类型
if (!isPasswordCharacterValid(decrypt)) {
throw new ServiceException(getCharacterRequirementErrorMessage());
}
// 3. 检查常见弱密码
if (containsWeakPassword(decrypt.toLowerCase())) {
throw new ServiceException("新密码包含常见的弱密码片段!");
}
// 4. 检查连续字符
if (systemConfig.getPasswordConfig().isRestrictConsecutiveChars() && containsConsecutiveCharacters(decrypt.toLowerCase(), systemConfig.getPasswordConfig().getMaxConsecutiveChars())) {
throw new ServiceException("新密码不能包含超过" + systemConfig.getPasswordConfig().getMaxConsecutiveChars() + "位连续字符!");
}
// 根据用户id查询用户信息
SysUser userInfo = userMapper.selectUserById(user.getUserId());
boolean isNewPassword = SecurityUtils.matchesPassword(decrypt, userInfo.getPassword());
if (isNewPassword) {
throw new ServiceException("新密码不能与旧密码相同!");
}
// 5. 判断新密码是否为系统默认密码
if (decrypt.equals(configService.selectConfigByKey("sys.user.initPassword"))) {
throw new ServiceException("新密码不能为系统默认密码!");
}
// 6. 检查用户名
if (systemConfig.getPasswordConfig().isExcludeUsernameInPassword() && decrypt.toLowerCase().contains(userInfo.getUserName().toLowerCase())) {
throw new ServiceException("新密码不能包含账号!");
}
}
/**
* 获取用户历史密码信息
* @param passwordHistory
* @return
*/
@Override
public List<UserPasswordHistory> checkPasswordExpiry(UserPasswordHistory passwordHistory) {
List<UserPasswordHistory> list = userMapper.checkPasswordExpiry(passwordHistory);
return list;
}
/**
* 检查密码是否包含超过n个连续字符
* @param password
* @param n
* @return
*/
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;
}
/**
* 判断密码是否包含常见弱密码
* @param password
* @return
*/
private boolean containsWeakPassword(String password) {
Set<String> weakPasswords = new HashSet<>(systemConfig.getPasswordConfig().getWeakPasswords());
for (String weakPwd : weakPasswords) {
if (password.contains(weakPwd)) {
return true;
}
}
return false;
}
/**
* 判断密码是否规范
* @param password
* @return
*/
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 (systemConfig.getPasswordConfig().isRequireUpperCase() && !hasUpperCase) {
return false;
}
if (systemConfig.getPasswordConfig().isRequireLowerCase() && !hasLowerCase) {
return false;
}
if (systemConfig.getPasswordConfig().isRequireDigit() && !hasDigit) {
return false;
}
return !(systemConfig.getPasswordConfig().isRequireSpecialChar() && !hasSpecialChar);
}
/**
* 根据配置返回密码不符合要求时的错误提示信息
*/
private String getCharacterRequirementErrorMessage() {
if (systemConfig.getPasswordConfig().isRequireUpperCase()) {
return "新密码必须包含大写字母!";
}
if (systemConfig.getPasswordConfig().isRequireLowerCase()) {
return "新密码必须包含小写字母!";
}
if (systemConfig.getPasswordConfig().isRequireDigit()) {
return "新密码必须包含数字!";
}
if (systemConfig.getPasswordConfig().isRequireSpecialChar()) {
return "新密码必须包含特殊字符!";
}
return "新密码不符合字符要求!";
}
/**
* 判断密码是否规范
* @param password
* @return
*/
private boolean isPasswordLengthValid(String password) {
return password.length() >= systemConfig.getPasswordConfig().getMinLength() && password.length() <= systemConfig.getPasswordConfig().getMaxLength();
}
/**
* 领料任务催办
*

View File

@ -301,6 +301,17 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sur.user_id = #{userId}
</select>
<select id="checkPasswordExpiry" resultType="com.bonus.sgzb.common.core.domain.UserPasswordHistory">
SELECT id AS id,
old_password AS oldPassword,
new_password AS newPassword,
change_timestamp AS changeTimestamp,
change_user AS changeUser
FROM sys_user_password_history
WHERE user_id = #{userId}
ORDER BY change_timestamp DESC
</select>
<insert id="insertUser" parameterType="com.bonus.sgzb.system.api.domain.SysUser" useGeneratedKeys="true" keyProperty="userId">
insert into sys_user(
<if test="userId != null and userId != 0">user_id,</if>
@ -334,6 +345,18 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
sysdate()
)
</insert>
<insert id="insertPasswordHistory">
INSERT INTO sys_user_password_history (user_id,
old_password,
new_password,
change_timestamp,
change_user)
VALUES (#{userId},
#{oldPassword},
#{password},
sysdate(),
#{changeUser});
</insert>
<update id="updateUser" parameterType="com.bonus.sgzb.system.api.domain.SysUser">
update sys_user