diff --git a/modules/i3plus-core-apiservice/src/main/java/cn/estsh/i3plus/core/apiservice/controller/busi/SysUserController.java b/modules/i3plus-core-apiservice/src/main/java/cn/estsh/i3plus/core/apiservice/controller/busi/SysUserController.java index 8e1af6b..db6085f 100644 --- a/modules/i3plus-core-apiservice/src/main/java/cn/estsh/i3plus/core/apiservice/controller/busi/SysUserController.java +++ b/modules/i3plus-core-apiservice/src/main/java/cn/estsh/i3plus/core/apiservice/controller/busi/SysUserController.java @@ -7,6 +7,7 @@ import cn.estsh.i3plus.core.api.iservice.busi.ISysRoleService; import cn.estsh.i3plus.core.api.iservice.busi.ISysUserInfoService; import cn.estsh.i3plus.core.api.iservice.busi.ISysUserPasswordService; import cn.estsh.i3plus.core.api.iservice.busi.ISysUserService; +import cn.estsh.i3plus.core.apiservice.util.SysUserPasswordUtil; import cn.estsh.i3plus.platform.common.convert.ConvertBean; import cn.estsh.i3plus.platform.common.exception.ImppExceptionEnum; import cn.estsh.i3plus.platform.common.tool.EncryptTool; @@ -562,8 +563,10 @@ public class SysUserController extends CoreBaseController { num = CommonConstWords.CONFIG_PWD_RESET_PASSWORD_DEFAULT - num; - String password = RandomStringUtils.random(6, true, false); - //随机生成密码的不检验密码的长度、复杂等信息 +// String password = RandomStringUtils.random(6, true, false); + + //根据系统密码配置的长度生成对应的密码 + String password = SysUserPasswordUtil.generateRandomPassword(); userPasswordService.updatePasswordResetLastModifyTime(user.getId(), password, false); //重置成随机密码会让用户首次登录修改密码 sysUserService.updateUserLoginNum(user.getId(),0); diff --git a/modules/i3plus-core-apiservice/src/main/java/cn/estsh/i3plus/core/apiservice/util/SysUserPasswordUtil.java b/modules/i3plus-core-apiservice/src/main/java/cn/estsh/i3plus/core/apiservice/util/SysUserPasswordUtil.java index f2e26ee..21328ec 100644 --- a/modules/i3plus-core-apiservice/src/main/java/cn/estsh/i3plus/core/apiservice/util/SysUserPasswordUtil.java +++ b/modules/i3plus-core-apiservice/src/main/java/cn/estsh/i3plus/core/apiservice/util/SysUserPasswordUtil.java @@ -13,6 +13,7 @@ import cn.estsh.impp.framework.boot.exception.ImppBusiException; import cn.estsh.impp.framework.boot.exception.ImppExceptionBuilder; import cn.estsh.impp.framework.boot.util.*; import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.lang3.RandomStringUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,15 +22,16 @@ import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Propagation; import org.springframework.transaction.annotation.Transactional; +import org.springframework.util.ObjectUtils; import javax.annotation.Resource; import javax.naming.NamingException; import javax.naming.ldap.LdapContext; import java.io.UnsupportedEncodingException; import java.security.NoSuchAlgorithmException; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.regex.Pattern; +import java.util.stream.Collectors; /** * @Description : @@ -53,6 +55,42 @@ public class SysUserPasswordUtil { protected ImppRedis redisCore; /** + * 大写字符char数组 + */ + public static char[] upperChars = new char[]{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'}; + /** + * 小写字符char数组 + */ + public static char[] lowerChars = new char[]{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'}; + /** + * 数字字符char数字 + */ + public static char[] numChars = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'}; + //char[] specialChars = new char[]{' ', '!', '"', '#', '$', '%', '&', '\'', '(', ')', '*', '+', ',', '-', '.', '/', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`', '{', '|', '}', '~'}; + /** + * 特殊字符char数组 + */ + //去除一些特殊字符 + public static char[] specialChars = new char[]{'!', '#', '$', '%', '&', '*', '+', '-', '?', '@', '^', '_', '~'}; + + /** + * 大写字符char数组的名称 + */ + public static String UPPER_CHAR_ARRAY_NAME = "UPPER"; + /** + * 小写字符char数组的名称 + */ + public static String LOWER_CHAR_ARRAY_NAME = "LOWER"; + /** + * 数字字符char数组的名称 + */ + public static String NUM_CHAR_ARRAY_NAME = "NUM"; + /** + * 特殊字符char数组的名称 + */ + public static String SPECIAL_CHAR_ARRAY_NAME = "SPECIAL"; + + /** * 密码加密 返回加密信息 * * @param password @@ -275,7 +313,7 @@ public class SysUserPasswordUtil { if (CollectionUtils.isNotEmpty(passwords)) { for (SysUserPassword password : passwords) { //防止日期转换错误 - if (StringUtils.isNotBlank(password.getCreateDatetime())){ + if (StringUtils.isNotBlank(password.getCreateDatetime())) { int day = TimeTool.getSecoundsBetweenTime(4, password.getCreateDatetime(), TimeTool.getNowTime(true)); if (day < lastDay) { lastDay = day; @@ -352,24 +390,24 @@ public class SysUserPasswordUtil { } catch (ImppBusiException e) { e.printStackTrace(); return ResultBean.fail(e); - }catch (Exception e){ + } catch (Exception e) { return ResultBean.fail(e); } } else { /* 检查密码有效期 */ - ResultBean result = checkLoginPasswordTimeOut(user); - if(!result.isSuccess()){ - return result; - } + ResultBean result = checkLoginPasswordTimeOut(user); + if (!result.isSuccess()) { + return result; + } /* 登录 长时间未登录锁定 */ result = checkLoginTimeOut(user); - if(!result.isSuccess()){ - return result; + if (!result.isSuccess()) { + return result; } /* 判断是否第一次登录 */ result = checkFirstLoginChangePwd(user); - if(!result.isSuccess()){ - return result; + if (!result.isSuccess()) { + return result; } } return ResultBean.success(); @@ -535,7 +573,7 @@ public class SysUserPasswordUtil { */ private ResultBean checkLoginTimeOut(SysUser user) { try { - if (StringUtils.isBlank(user.getUserLoginLastDateTime())){ + if (StringUtils.isBlank(user.getUserLoginLastDateTime())) { return ResultBean.success("上次登录时间为空"); } int loginDayMax = RedisCacheTool.getSysConfigIntVal(CommonConstWords.CONFIG_USER_LOGIN_DAY_OUT, CommonConstWords.CONFIG_USER_LOGIN_DAY_OUT_DEFAULT); @@ -600,4 +638,65 @@ public class SysUserPasswordUtil { return ResultBean.success(); } + + /** + * 根据密码安全策略里面的规则生成随机密码,重复性检验和正则表达式检验不进行校验 + * 密码保存规则里面有正则校验,正则校验可能会与其他规则冲突,导致生成的密码无法通过规则校验 + * 目前重置密码不会进行密码规则的校验 + * + * @return string + */ + public static String generateRandomPassword() { + int length = RedisCacheTool.getSysConfigIntVal(CommonConstWords.CONFIG_PWD_LENGTH, CommonConstWords.CONFIG_PWD_LENGTH_DEFAULT); + //todo: 修改密码长度的接口要做校验,长度不能超过最大值 + if (length < CommonConstWords.CONFIG_PWD_LENGTH_DEFAULT) { + length = CommonConstWords.CONFIG_PWD_LENGTH_DEFAULT; + } + //四种类型的字符一定会有,所以先随机占用4个位置 + Random random = new Random(); + String[] typeArray = new String[]{UPPER_CHAR_ARRAY_NAME, LOWER_CHAR_ARRAY_NAME, NUM_CHAR_ARRAY_NAME, SPECIAL_CHAR_ARRAY_NAME}; + char[] randomCharArray = new char[length]; + int top = length; + int[] indexArray = new int[length]; + for (int i = 0; i < indexArray.length; i++) { + indexArray[i] = i; + } + Map indexMap = new HashMap<>(length); + //确定四个必须要的字符的位置,剩下的位置的字符随机从四种中选择 + for (int i = 0; i < 4; i++) { + int index = random.nextInt(top); + indexMap.put(indexArray[index], typeArray[i]); + indexArray[index] = indexArray[top - 1]; + top--; + } + for (int i = 0; i < randomCharArray.length; i++) { + //判断对应字符的位置是否已经被占用 + if (!ObjectUtils.isEmpty(indexMap.get(i))) { + randomCharArray[i] = getRandomChar(indexMap.get(i), random); + } else { + //todo:这里可以把所有char合并一个数组做减少typeArray的random,直接从所有可选字符合并的大数组里面选一个字符 + randomCharArray[i] = getRandomChar(typeArray[random.nextInt(typeArray.length)], random); + } + } + return String.valueOf(randomCharArray); + } + + /** + * 根据同的字符类型生成对应类型的随机字符 + * @param key + * @param random + * @return + */ + public static char getRandomChar(String key, Random random) { + if (UPPER_CHAR_ARRAY_NAME.equals(key)) { + return upperChars[random.nextInt(upperChars.length)]; + } else if (LOWER_CHAR_ARRAY_NAME.equals(key)) { + return lowerChars[random.nextInt(lowerChars.length)]; + } else if (NUM_CHAR_ARRAY_NAME.equals(key)) { + return numChars[random.nextInt(numChars.length)]; + } else { + return specialChars[random.nextInt(specialChars.length)]; + } + } + }