mirror of
https://github.com/continew-org/continew-admin.git
synced 2025-09-11 06:57:12 +08:00
feat: 禁止密码过期用户访问业务接口
This commit is contained in:
@@ -97,6 +97,16 @@ public class LoginUser implements Serializable {
|
|||||||
*/
|
*/
|
||||||
private LocalDateTime loginTime;
|
private LocalDateTime loginTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 最后一次修改密码时间
|
||||||
|
*/
|
||||||
|
private LocalDateTime pwdResetTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录时系统设置的密码过期天数
|
||||||
|
*/
|
||||||
|
private Integer passwordExpirationDays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否为管理员
|
* 是否为管理员
|
||||||
*
|
*
|
||||||
|
@@ -25,9 +25,11 @@ import cn.hutool.extra.servlet.JakartaServletUtil;
|
|||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import top.continew.admin.common.constant.CacheConstants;
|
import top.continew.admin.common.constant.CacheConstants;
|
||||||
|
import top.continew.admin.common.constant.SysConstants;
|
||||||
import top.continew.admin.common.model.dto.LoginUser;
|
import top.continew.admin.common.model.dto.LoginUser;
|
||||||
import top.continew.starter.core.util.ExceptionUtils;
|
import top.continew.starter.core.util.ExceptionUtils;
|
||||||
import top.continew.starter.core.util.IpUtils;
|
import top.continew.starter.core.util.IpUtils;
|
||||||
|
import top.continew.starter.core.util.validate.CheckUtils;
|
||||||
import top.continew.starter.extension.crud.service.CommonUserService;
|
import top.continew.starter.extension.crud.service.CommonUserService;
|
||||||
import top.continew.starter.web.util.ServletUtils;
|
import top.continew.starter.web.util.ServletUtils;
|
||||||
|
|
||||||
@@ -75,6 +77,16 @@ public class LoginHelper {
|
|||||||
* @throws NotLoginException 未登录异常
|
* @throws NotLoginException 未登录异常
|
||||||
*/
|
*/
|
||||||
public static LoginUser getLoginUser() throws NotLoginException {
|
public static LoginUser getLoginUser() throws NotLoginException {
|
||||||
|
return getLoginUser(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 登录用户信息
|
||||||
|
*
|
||||||
|
* @param checkPasswordExpired 是否校验密码过期
|
||||||
|
* @throws NotLoginException 未登录异常
|
||||||
|
*/
|
||||||
|
public static LoginUser getLoginUser(boolean checkPasswordExpired) throws NotLoginException {
|
||||||
StpUtil.checkLogin();
|
StpUtil.checkLogin();
|
||||||
LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConstants.LOGIN_USER_KEY);
|
LoginUser loginUser = (LoginUser)SaHolder.getStorage().get(CacheConstants.LOGIN_USER_KEY);
|
||||||
if (null != loginUser) {
|
if (null != loginUser) {
|
||||||
@@ -83,9 +95,33 @@ public class LoginHelper {
|
|||||||
SaSession tokenSession = StpUtil.getTokenSession();
|
SaSession tokenSession = StpUtil.getTokenSession();
|
||||||
loginUser = (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
|
loginUser = (LoginUser)tokenSession.get(CacheConstants.LOGIN_USER_KEY);
|
||||||
SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
|
SaHolder.getStorage().set(CacheConstants.LOGIN_USER_KEY, loginUser);
|
||||||
|
CheckUtils.throwIf(checkPasswordExpired && isPasswordExpired(loginUser), "密码已过期,请立即修改。");
|
||||||
return loginUser;
|
return loginUser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 密码是否已过期
|
||||||
|
*
|
||||||
|
* @param loginUser 登录用户
|
||||||
|
* @return 是否过期
|
||||||
|
*/
|
||||||
|
public static boolean isPasswordExpired(LoginUser loginUser) {
|
||||||
|
if (loginUser == null) {
|
||||||
|
loginUser = getLoginUser();
|
||||||
|
}
|
||||||
|
LocalDateTime pwdResetTime = loginUser.getPwdResetTime();
|
||||||
|
Integer passwordExpirationDays = loginUser.getPasswordExpirationDays();
|
||||||
|
// 永久有效
|
||||||
|
if (passwordExpirationDays == null || passwordExpirationDays <= SysConstants.NO) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// 初始密码也提示修改
|
||||||
|
if (pwdResetTime == null) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return pwdResetTime.plusDays(passwordExpirationDays).isBefore(LocalDateTime.now());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据 Token 获取登录用户信息
|
* 根据 Token 获取登录用户信息
|
||||||
*
|
*
|
||||||
@@ -109,6 +145,16 @@ public class LoginHelper {
|
|||||||
return getLoginUser().getId();
|
return getLoginUser().getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取登录用户 ID
|
||||||
|
*
|
||||||
|
* @param checkPasswordExpired 是否校验密码过期
|
||||||
|
* @return 登录用户 ID
|
||||||
|
*/
|
||||||
|
public static Long getUserId(boolean checkPasswordExpired) {
|
||||||
|
return getLoginUser(checkPasswordExpired).getId();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取登录用户名
|
* 获取登录用户名
|
||||||
*
|
*
|
||||||
|
@@ -61,6 +61,8 @@ import java.time.Duration;
|
|||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import static top.continew.admin.system.enums.PasswordPolicyEnum.PASSWORD_EXPIRATION_DAYS;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 登录业务实现
|
* 登录业务实现
|
||||||
*
|
*
|
||||||
@@ -199,6 +201,7 @@ public class LoginServiceImpl implements LoginService {
|
|||||||
loginUser.setPermissions(permissionService.listPermissionByUserId(userId));
|
loginUser.setPermissions(permissionService.listPermissionByUserId(userId));
|
||||||
loginUser.setRoleCodes(permissionService.listRoleCodeByUserId(userId));
|
loginUser.setRoleCodes(permissionService.listRoleCodeByUserId(userId));
|
||||||
loginUser.setRoles(roleService.listByUserId(userId));
|
loginUser.setRoles(roleService.listByUserId(userId));
|
||||||
|
loginUser.setPasswordExpirationDays(optionService.getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name()));
|
||||||
return LoginHelper.login(loginUser);
|
return LoginHelper.login(loginUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -29,7 +29,6 @@ import top.continew.starter.data.mybatis.plus.service.IService;
|
|||||||
import top.continew.starter.extension.crud.service.BaseService;
|
import top.continew.starter.extension.crud.service.BaseService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -90,14 +89,6 @@ public interface UserService extends BaseService<UserResp, UserDetailResp, UserQ
|
|||||||
*/
|
*/
|
||||||
void updatePassword(String oldPassword, String newPassword, Long id);
|
void updatePassword(String oldPassword, String newPassword, Long id);
|
||||||
|
|
||||||
/**
|
|
||||||
* 密码是否已过期
|
|
||||||
*
|
|
||||||
* @param pwdResetTime 上次重置密码时间
|
|
||||||
* @return 是否过期
|
|
||||||
*/
|
|
||||||
boolean isPasswordExpired(LocalDateTime pwdResetTime);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改手机号
|
* 修改手机号
|
||||||
*
|
*
|
||||||
|
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package top.continew.admin.system.service.impl;
|
package top.continew.admin.system.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.bean.BeanUtil;
|
||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.img.ImgUtil;
|
import cn.hutool.core.img.ImgUtil;
|
||||||
@@ -210,20 +211,8 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes
|
|||||||
baseMapper.updateById(user);
|
baseMapper.updateById(user);
|
||||||
// 保存历史密码
|
// 保存历史密码
|
||||||
userPasswordHistoryService.add(id, password, passwordRepetitionTimes);
|
userPasswordHistoryService.add(id, password, passwordRepetitionTimes);
|
||||||
}
|
// 修改后登出
|
||||||
|
StpUtil.logout();
|
||||||
@Override
|
|
||||||
public boolean isPasswordExpired(LocalDateTime pwdResetTime) {
|
|
||||||
// 永久有效
|
|
||||||
int passwordExpirationDays = optionService.getValueByCode2Int(PASSWORD_EXPIRATION_DAYS.name());
|
|
||||||
if (passwordExpirationDays <= SysConstants.NO) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// 初始密码也提示修改
|
|
||||||
if (pwdResetTime == null) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return pwdResetTime.plusDays(passwordExpirationDays).isBefore(LocalDateTime.now());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@@ -123,12 +123,12 @@ public class AuthController {
|
|||||||
@Operation(summary = "获取用户信息", description = "获取登录用户信息")
|
@Operation(summary = "获取用户信息", description = "获取登录用户信息")
|
||||||
@GetMapping("/user/info")
|
@GetMapping("/user/info")
|
||||||
public R<UserInfoResp> getUserInfo() {
|
public R<UserInfoResp> getUserInfo() {
|
||||||
LoginUser loginUser = LoginHelper.getLoginUser();
|
LoginUser loginUser = LoginHelper.getLoginUser(false);
|
||||||
UserDetailResp userDetailResp = userService.get(loginUser.getId());
|
UserDetailResp userDetailResp = userService.get(loginUser.getId());
|
||||||
UserInfoResp userInfoResp = BeanUtil.copyProperties(userDetailResp, UserInfoResp.class);
|
UserInfoResp userInfoResp = BeanUtil.copyProperties(userDetailResp, UserInfoResp.class);
|
||||||
userInfoResp.setPermissions(loginUser.getPermissions());
|
userInfoResp.setPermissions(loginUser.getPermissions());
|
||||||
userInfoResp.setRoles(loginUser.getRoleCodes());
|
userInfoResp.setRoles(loginUser.getRoleCodes());
|
||||||
userInfoResp.setPwdExpired(userService.isPasswordExpired(userDetailResp.getPwdResetTime()));
|
userInfoResp.setPwdExpired(LoginHelper.isPasswordExpired(loginUser));
|
||||||
return R.ok(userInfoResp);
|
return R.ok(userInfoResp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,6 +136,6 @@ public class AuthController {
|
|||||||
@Operation(summary = "获取路由信息", description = "获取登录用户的路由信息")
|
@Operation(summary = "获取路由信息", description = "获取登录用户的路由信息")
|
||||||
@GetMapping("/route")
|
@GetMapping("/route")
|
||||||
public R<List<RouteResp>> listRoute() {
|
public R<List<RouteResp>> listRoute() {
|
||||||
return R.ok(loginService.buildRouteTree(LoginHelper.getUserId()));
|
return R.ok(loginService.buildRouteTree(LoginHelper.getUserId(false)));
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -94,7 +94,7 @@ public class UserCenterController {
|
|||||||
String rawNewPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq
|
String rawNewPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq
|
||||||
.getNewPassword()));
|
.getNewPassword()));
|
||||||
ValidationUtils.throwIfNull(rawNewPassword, "新密码解密失败");
|
ValidationUtils.throwIfNull(rawNewPassword, "新密码解密失败");
|
||||||
userService.updatePassword(rawOldPassword, rawNewPassword, LoginHelper.getUserId());
|
userService.updatePassword(rawOldPassword, rawNewPassword, LoginHelper.getUserId(false));
|
||||||
return R.ok("修改成功,请牢记你的新密码");
|
return R.ok("修改成功,请牢记你的新密码");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user