需求修改及优化
This commit is contained in:
parent
16af2a6323
commit
f1ccc8f38e
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
com.bonus.sgzb.common.core.utils.SpringUtils
|
||||
com.bonus.sgzb.common.core.utils.SystemConfig
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
/**
|
||||
* 领料任务催办
|
||||
*
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue