✨ #5631 建议增加密码过期提示或强制修改密码需求

This commit is contained in:
冷冷 committed 2024-05-04 11:33:43 +08:00
1 parent 690568aa82
commit 079d70e204
12 files changed
+303 -162

No files matched your search

+3 -1
View File
@@ -1236,6 +1236,8 @@ CREATE TABLE `sys_user` (
`create_time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`lock_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '锁定标记,0未锁定,9已锁定',
`password_expire_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '密码是否过期,0未过期,9已过期',
`password_modify_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
`del_flag` char(1) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT '0' COMMENT '删除标记,0未删除,1已删除',
`wx_openid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '微信登录openId',
`mini_openid` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT NULL COMMENT '小程序openId',
@@ -1255,7 +1257,7 @@ CREATE TABLE `sys_user` (
-- Records of sys_user
-- ----------------------------
BEGIN;
INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$c/Ae0pRjJtMZg3BnvVpO.eIK6WYWVbKTzqgdy3afR7w.vd.xi3Mgy', '', '13054729089', '/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png', '管理员666777', '管理员', 'sw@mail.pigxl.vip', 4, ' ', 'admin', '2018-04-20 07:15:18', '2023-04-03 14:00:06', '0', '0', NULL, 'oBxPy5E-v82xWGsfzZVzkD3wEX64', NULL, 'log4j', NULL, NULL,NULL,1);
INSERT INTO `sys_user` VALUES (1, 'admin', '$2a$10$c/Ae0pRjJtMZg3BnvVpO.eIK6WYWVbKTzqgdy3afR7w.vd.xi3Mgy', '', '13054729089', '/admin/sys-file/local/2a14ae08150e483c93e12ac8934173e2.png', '管理员666777', '管理员', 'sw@mail.pigxl.vip', 4, ' ', 'admin', '2018-04-20 07:15:18', '2023-04-03 14:00:06', '0', '0', NULL, '0', NULL, 'oBxPy5E-v82xWGsfzZVzkD3wEX64', NULL, 'log4j', NULL, NULL,NULL,1);
COMMIT;
-- ----------------------------
@@ -265,6 +265,12 @@ public abstract class OAuth2ResourceOwnerBaseAuthenticationProvider<T extends OA
*/
private OAuth2AuthenticationException oAuth2AuthenticationException(Authentication authentication,
AuthenticationException authenticationException) {
// OAuth2AuthenticationException 直接返回
if (authenticationException instanceof OAuth2AuthenticationException) {
return (OAuth2AuthenticationException) authenticationException;
}
if (authenticationException instanceof UsernameNotFoundException) {
return new OAuth2AuthenticationException(new OAuth2Error(OAuth2ErrorCodesExpand.USERNAME_NOT_FOUND,
this.messages.getMessage("JdbcDaoImpl.notFound", new Object[] { authentication.getName() },
@@ -42,71 +42,78 @@ import java.util.Set;
*/
public interface PigxUserDetailsService extends UserDetailsService, Ordered {
/**
* 是否支持此客户端校验
* @param clientId 请求客户端
* @param grantType 授权类型
* @return true/false
*/
default boolean support(String clientId, String grantType) {
return true;
}
/**
* 是否支持此客户端校验
*
* @param clientId 请求客户端
* @param grantType 授权类型
* @return true/false
*/
default boolean support(String clientId, String grantType) {
return true;
}
/**
* 排序值 默认取最大的
* @return 排序值
*/
default int getOrder() {
return 0;
}
/**
* 排序值 默认取最大的
*
* @return 排序值
*/
default int getOrder() {
return 0;
}
/**
* 构建userdetails
* @param result 用户信息
* @return UserDetails
* @throws UsernameNotFoundException
*/
default UserDetails getUserDetails(R<UserInfo> result) {
// @formatter:off
/**
* 构建userdetails
*
* @param result 用户信息
* @return UserDetails
* @throws UsernameNotFoundException
*/
default UserDetails getUserDetails(R<UserInfo> result) {
// @formatter:off
return RetOps.of(result)
.getData()
.map(this::convertUserDetails)
.orElseThrow(() -> new UsernameNotFoundException("用户不存在"));
// @formatter:on
}
}
/**
* UserInfo 转 UserDetails
* @param info
* @return 返回UserDetails对象
*/
default UserDetails convertUserDetails(UserInfo info) {
Set<String> dbAuthsSet = new HashSet<>();
if (ArrayUtil.isNotEmpty(info.getRoles())) {
// 获取角色
Arrays.stream(info.getRoles()).forEach(roleId -> dbAuthsSet.add(SecurityConstants.ROLE + roleId));
// 获取资源
dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));
/**
* UserInfo 转 UserDetails
*
* @param info
* @return 返回UserDetails对象
*/
default UserDetails convertUserDetails(UserInfo info) {
Set<String> dbAuthsSet = new HashSet<>();
if (ArrayUtil.isNotEmpty(info.getRoles())) {
// 获取角色
Arrays.stream(info.getRoles()).forEach(roleId -> dbAuthsSet.add(SecurityConstants.ROLE + roleId));
// 获取资源
dbAuthsSet.addAll(Arrays.asList(info.getPermissions()));
}
Collection<? extends GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
SysUser user = info.getSysUser();
// 构造security用户
}
Collection<? extends GrantedAuthority> authorities = AuthorityUtils
.createAuthorityList(dbAuthsSet.toArray(new String[0]));
SysUser user = info.getSysUser();
return new PigxUser(user.getUserId(), user.getUsername(), user.getDeptId(), user.getPhone(), user.getAvatar(),
user.getNickname(), user.getName(), user.getEmail(), user.getTenantId(),
SecurityConstants.BCRYPT + user.getPassword(), true, true, UserTypeEnum.TOB.getStatus(), true,
!CommonConstants.STATUS_LOCK.equals(user.getLockFlag()), authorities);
}
// 构造security用户
return new PigxUser(user.getUserId(), user.getUsername(), user.getDeptId(), user.getPhone(), user.getAvatar(),
user.getNickname(), user.getName(), user.getEmail(), user.getTenantId(),
SecurityConstants.BCRYPT + user.getPassword()
, true, true, UserTypeEnum.TOB.getStatus()
, !CommonConstants.STATUS_LOCK.equals(user.getPasswordExpireFlag()) // 密码过期判断
, !CommonConstants.STATUS_LOCK.equals(user.getLockFlag()), authorities);
}
/**
* 通过用户实体查询
* @param pigxUser user
* @return
*/
default UserDetails loadUserByUser(PigxUser pigxUser) {
return this.loadUserByUsername(pigxUser.getUsername());
}
/**
* 通过用户实体查询
*
* @param pigxUser user
* @return
*/
default UserDetails loadUserByUser(PigxUser pigxUser) {
return this.loadUserByUsername(pigxUser.getUsername());
}
}
@@ -114,6 +114,20 @@ public class SysUser extends Model<SysUser> implements Serializable {
@Schema(description = "锁定标记")
private String lockFlag;
/**
* 密码过期标记
*/
@Schema(description = "密码过期标记")
private String passwordExpireFlag;
/**
* 密码修改时间
*/
@Schema(description = "密码修改时间")
private LocalDateTime passwordModifyTime;
/**
* 手机号
*/
@@ -112,6 +112,18 @@ public class UserVO implements Serializable {
@Schema(description = "锁定标记,0:正常,9:已锁定")
private String lockFlag;
/**
* 密码过期标记
*/
@Schema(description = "密码过期标记")
private String passwordExpireFlag;
/**
* 密码修改时间
*/
@Schema(description = "密码修改时间")
private LocalDateTime passwordModifyTime;
/**
* 手机号
*/
@@ -18,24 +18,37 @@ import org.springframework.web.bind.annotation.RestController;
* <p>
* 客户端注册功能 register.user = false
*/
@Inner(value = false)
@RestController
@RequestMapping("/register")
@RequiredArgsConstructor
@ConditionalOnProperty(name = "register.user", matchIfMissing = true)
public class RegisterController {
private final SysUserService userService;
private final SysUserService userService;
/**
* 注册用户
* @param userDto 用户信息
* @return success/false
*/
@Inner(value = false)
@SysLog("注册用户")
@PostMapping("/user")
public R<Boolean> registerUser(@RequestBody UserDTO userDto) {
return userService.registerUser(userDto);
}
/**
* 注册用户
*
* @param userDto 用户信息
* @return success/false
*/
@SysLog("注册用户")
@PostMapping("/user")
@ConditionalOnProperty(name = "register.user", matchIfMissing = true)
public R<Boolean> registerUser(@RequestBody UserDTO userDto) {
return userService.registerUser(userDto);
}
/**
* 重置用户密码
*
* @param userDto 用户信息
* @return success/false
*/
@SysLog("重置用户密码")
@PostMapping("/password")
public R<Boolean> resetUserPassword(@RequestBody UserDTO userDto) {
return userService.resetUserPassword(userDto);
}
}
@@ -243,7 +243,7 @@ public class SysUserController {
*/
@PostMapping("/check")
public R check(String password) {
return userService.checkPassword(password);
return userService.checkPassword(SecurityUtils.getUser().getUsername(),password);
}
/**
@@ -38,111 +38,151 @@ import java.util.List;
*/
public interface SysUserService extends IService<SysUser> {
/**
* 查询用户信息
* @param sysUser 用户
* @return userInfo
*/
UserInfo findUserInfo(SysUser sysUser);
/**
* 查询用户信息
*
* @param sysUser 用户
* @return userInfo
*/
UserInfo findUserInfo(SysUser sysUser);
/**
* 分页查询用户信息(含有角色信息)
* @param page 分页对象
* @param userDTO 参数列表
* @return
*/
IPage getUsersWithRolePage(Page page, UserDTO userDTO);
/**
* 分页查询用户信息(含有角色信息)
*
* @param page 分页对象
* @param userDTO 参数列表
* @return
*/
IPage getUsersWithRolePage(Page page, UserDTO userDTO);
/**
* 删除用户
* @param ids 用户
* @return boolean
*/
Boolean deleteUserByIds(Long[] ids);
/**
* 删除用户
*
* @param ids 用户
* @return boolean
*/
Boolean deleteUserByIds(Long[] ids);
/**
* 更新当前用户基本信息
* @param userDto 用户信息
* @return Boolean
*/
R<Boolean> updateUserInfo(UserDTO userDto);
/**
* 更新当前用户基本信息
*
* @param userDto 用户信息
* @return Boolean
*/
R<Boolean> updateUserInfo(UserDTO userDto);
/**
* 更新指定用户信息
* @param userDto 用户信息
* @return
*/
Boolean updateUser(UserDTO userDto);
/**
* 更新指定用户信息
*
* @param userDto 用户信息
* @return
*/
Boolean updateUser(UserDTO userDto);
/**
* 通过ID查询用户信息
* @param id 用户ID
* @return 用户信息
*/
UserVO selectUserVoById(Long id);
/**
* 通过ID查询用户信息
*
* @param id 用户ID
* @return 用户信息
*/
UserVO selectUserVoById(Long id);
/**
* 查询上级部门的用户信息
* @param username 用户名
* @return R
*/
List<SysUser> listAncestorUsers(String username);
/**
* 查询上级部门的用户信息
*
* @param username 用户名
* @return R
*/
List<SysUser> listAncestorUsers(String username);
/**
* 保存用户信息
* @param userDto DTO 对象
* @return success/fail
*/
Boolean saveUser(UserDTO userDto);
/**
* 保存用户信息
*
* @param userDto DTO 对象
* @return success/fail
*/
Boolean saveUser(UserDTO userDto);
/**
* 查询全部的用户
* @param userDTO 查询条件
* @param ids 目标列表
* @return list
*/
List<UserExcelVO> listUser(UserDTO userDTO, Long[] ids);
/**
* 查询全部的用户
*
* @param userDTO 查询条件
* @param ids 目标列表
* @return list
*/
List<UserExcelVO> listUser(UserDTO userDTO, Long[] ids);
/**
* excel 导入用户
* @param excelVOList excel 列表数据
* @param bindingResult 错误数据
* @return ok fail
*/
R importUser(List<UserExcelVO> excelVOList, BindingResult bindingResult);
/**
* excel 导入用户
*
* @param excelVOList excel 列表数据
* @param bindingResult 错误数据
* @return ok fail
*/
R importUser(List<UserExcelVO> excelVOList, BindingResult bindingResult);
/**
* 注册用户
* @param userDto 用户信息
* @return success/false
*/
R<Boolean> registerUser(UserDTO userDto);
/**
* 注册用户
*
* @param userDto 用户信息
* @return success/false
*/
R<Boolean> registerUser(UserDTO userDto);
/**
* 锁定用户
* @param username
* @return
*/
R<Boolean> lockUser(String username);
/**
* 锁定用户
*
* @param username 用户名
* @return R
*/
R<Boolean> lockUser(String username);
R changePassword(UserDTO userDto);
/**
* 修改密码
*
* @param userDto 用户信息
* @return
*/
R changePassword(UserDTO userDto);
R unbinding(String type);
/**
* 解绑社交登录
*
* @param type 社交登录类型
* @return R
*/
R unbinding(String type);
R checkPassword(String password);
/**
* 校验密码
*
* @param username 用户名
* @param password 密码
* @return R
*/
R checkPassword(String username, String password);
/**
* 根据角色ID列表获取用户ID列表接口
* @param roleIdList 角色ID列表
* @return List<Long> 返回结果对象,包含根据角色ID列表获取到的用户ID列表信息
*/
List<Long> listUserIdByRoleIds(List<Long> roleIdList);
/**
* 根据角色ID列表获取用户ID列表接口
*
* @param roleIdList 角色ID列表
* @return List<Long> 返回结果对象,包含根据角色ID列表获取到的用户ID列表信息
*/
List<Long> listUserIdByRoleIds(List<Long> roleIdList);
/**
* 根据部门ID列表获取用户ID列表接口
* @param deptIdList 部门ID列表
* @return List<Long> 返回结果对象,包含根据部门ID列表获取到的用户ID列表信息
*/
List<SysUser> listUserIdByDeptIds(List<Long> deptIdList);
/**
* 根据部门ID列表获取用户ID列表接口
*
* @param deptIdList 部门ID列表
* @return List<Long> 返回结果对象,包含根据部门ID列表获取到的用户ID列表信息
*/
List<SysUser> listUserIdByDeptIds(List<Long> deptIdList);
/**
* 重置用户密码
*
* @param userDto 用户信息
* @return
*/
R<Boolean> resetUserPassword(UserDTO userDto);
}
@@ -44,6 +44,7 @@ import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
@@ -157,6 +158,7 @@ public class ConnectServiceImpl implements ConnectService {
userDTO.setEmail(userObj.getStr("email"));
// 初始化密码为 手机号
userDTO.setPassword(userObj.getStr("mobile"));
userDTO.setPasswordModifyTime(LocalDateTime.now());
sysUserService.saveUser(userDTO);
}
@@ -43,6 +43,7 @@ import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -157,6 +158,7 @@ public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant
// 构造初始化用户
SysUser user = new SysUser();
user.setUsername(defaultUsername);
user.setPasswordModifyTime(LocalDateTime.now());
user.setPassword(ENCODER.encode(defaultPassword));
user.setDeptId(dept.getDeptId());
userService.save(user);
@@ -40,6 +40,7 @@ import com.pig4cloud.pigx.admin.mapper.SysUserRoleMapper;
import com.pig4cloud.pigx.admin.service.*;
import com.pig4cloud.pigx.common.audit.annotation.Audit;
import com.pig4cloud.pigx.common.core.constant.CacheConstants;
import com.pig4cloud.pigx.common.core.constant.CommonConstants;
import com.pig4cloud.pigx.common.core.exception.ErrorCodes;
import com.pig4cloud.pigx.common.core.util.MsgUtils;
import com.pig4cloud.pigx.common.core.util.R;
@@ -105,6 +106,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
sysUser.setCreateBy(userDto.getUsername());
sysUser.setUpdateBy(userDto.getUsername());
sysUser.setPassword(ENCODER.encode(userDto.getPassword()));
sysUser.setPasswordModifyTime(LocalDateTime.now());
baseMapper.insert(sysUser);
// 保存用户岗位信息
Optional.ofNullable(userDto.getPost()).ifPresent(posts -> {
@@ -403,6 +405,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
userDTO.setEmail(excel.getEmail());
userDTO.setLockFlag(excel.getLockFlag());
// 批量导入初始密码为手机号
userDTO.setPasswordModifyTime(LocalDateTime.now());
userDTO.setPassword(userDTO.getPhone());
// 根据部门名称查询部门ID
userDTO.setDeptId(deptOptional.get().getDeptId());
@@ -481,6 +484,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
this.update(Wrappers.<SysUser>lambdaUpdate()
.set(SysUser::getPassword, password)
.set(SysUser::getPasswordModifyTime, LocalDateTime.now())
.eq(SysUser::getUserId, user.getUserId()));
return R.ok();
}
@@ -522,8 +526,7 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
}
@Override
public R checkPassword(String password) {
String username = SecurityUtils.getUser().getUsername();
public R checkPassword(String username, String password) {
SysUser condition = new SysUser();
condition.setUsername(username);
SysUser sysUser = this.getOne(new QueryWrapper<>(condition));
@@ -536,6 +539,36 @@ public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> impl
}
}
/**
* 重置用户密码
*
* @param userDto 用户信息
* @return
*/
@Override
@CacheEvict(value = CacheConstants.USER_DETAILS, key = "#userDto.username")
public R<Boolean> resetUserPassword(UserDTO userDto) {
// 校验密码
R checkedPassword = checkPassword(userDto.getUsername(), userDto.getPassword());
if (!checkedPassword.isOk()) {
return checkedPassword;
}
// 新密码校验
if (StrUtil.equals(userDto.getPassword(), userDto.getNewpassword1())) {
return R.failed("新旧密码不能相同");
}
// 重置密码
String password = ENCODER.encode(userDto.getNewpassword1());
this.update(Wrappers.<SysUser>lambdaUpdate()
.set(SysUser::getPassword, password)
.set(SysUser::getPasswordModifyTime, LocalDateTime.now())
.set(SysUser::getPasswordExpireFlag, CommonConstants.STATUS_NORMAL)
.eq(SysUser::getUsername, userDto.getUsername()));
return R.ok();
}
@Override
public List<Long> listUserIdByRoleIds(List<Long> roleIdList) {
return sysUserRoleMapper.selectList(Wrappers.<SysUserRole>lambdaQuery().in(SysUserRole::getRoleId, roleIdList))
@@ -37,6 +37,8 @@
<result column="ucreate_time" property="createTime"/>
<result column="uupdate_time" property="updateTime"/>
<result column="lock_flag" property="lockFlag"/>
<result column="password_expire_flag" property="passwordExpireFlag"/>
<result column="password_modify_time" property="passwordModifyTime"/>
<result column="udel_flag" property="delFlag"/>
<result column="dept_id" property="deptId"/>
<result column="tenant_id" property="tenantId"/>
@@ -66,6 +68,8 @@
u.dept_id,
u.del_flag,
u.lock_flag,
u.password_expire_flag,
u.password_modify_time,
u.tenant_id,
u.create_by,
u.create_time ucreate_time,
@@ -93,6 +97,8 @@
u.osc_id,
u.del_flag,
u.lock_flag,
u.password_expire_flag,
u.password_modify_time,
u.tenant_id,
u.nickname,
u.name,
@@ -142,6 +148,8 @@
u.update_time uupdate_time,
u.del_flag,
u.lock_flag,
u.password_expire_flag,
u.password_modify_time,
u.tenant_id,
u.nickname,
u.name,
@@ -188,6 +196,8 @@
u.update_time uupdate_time,
u.del_flag,
u.lock_flag,
u.password_expire_flag,
u.password_modify_time,
u.tenant_id,
u.nickname,
u.name,