diff --git a/continew-common/src/main/java/top/continew/admin/common/util/SecureUtils.java b/continew-common/src/main/java/top/continew/admin/common/util/SecureUtils.java index 6e7ab53b..14805207 100644 --- a/continew-common/src/main/java/top/continew/admin/common/util/SecureUtils.java +++ b/continew-common/src/main/java/top/continew/admin/common/util/SecureUtils.java @@ -17,9 +17,12 @@ package top.continew.admin.common.util; import cn.hutool.core.codec.Base64; +import cn.hutool.core.util.ReUtil; import cn.hutool.crypto.SecureUtil; import cn.hutool.crypto.asymmetric.KeyType; import top.continew.admin.common.config.RsaProperties; +import top.continew.admin.common.constant.RegexConstants; +import top.continew.starter.core.util.ExceptionUtils; import top.continew.starter.core.util.validation.ValidationUtils; /** @@ -78,4 +81,35 @@ public class SecureUtils { public static String decryptByRsaPrivateKey(String data, String privateKey) { return new String(SecureUtil.rsa(privateKey, null).decrypt(Base64.decode(data), KeyType.PrivateKey)); } + + /** + * 解密密码 + * + * @param encryptedPasswordByRsaPublicKey 密码(已被 Rsa 公钥加密) + * @param errorMsg 错误信息 + * @return 解密后的密码 + */ + public static String decryptPasswordByRsaPrivateKey(String encryptedPasswordByRsaPublicKey, String errorMsg) { + return decryptPasswordByRsaPrivateKey(encryptedPasswordByRsaPublicKey, errorMsg, false); + } + + /** + * 解密密码 + * + * @param encryptedPasswordByRsaPublicKey 密码(已被 Rsa 公钥加密) + * @param errorMsg 错误信息 + * @param isVerifyPattern 是否验证密码格式 + * @return 解密后的密码 + */ + public static String decryptPasswordByRsaPrivateKey(String encryptedPasswordByRsaPublicKey, + String errorMsg, + boolean isVerifyPattern) { + String rawPassword = ExceptionUtils.exToNull(() -> decryptByRsaPrivateKey(encryptedPasswordByRsaPublicKey)); + ValidationUtils.throwIfBlank(rawPassword, errorMsg); + if (isVerifyPattern) { + ValidationUtils.throwIf(!ReUtil + .isMatch(RegexConstants.PASSWORD, rawPassword), "密码长度为 8-32 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字"); + } + return rawPassword; + } } diff --git a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantController.java b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantController.java index 5bb8e55d..066ecb7b 100644 --- a/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantController.java +++ b/continew-plugin/continew-plugin-tenant/src/main/java/top/continew/admin/tenant/controller/TenantController.java @@ -35,8 +35,6 @@ import top.continew.admin.tenant.model.req.TenantReq; import top.continew.admin.tenant.model.resp.TenantDetailResp; import top.continew.admin.tenant.model.resp.TenantResp; import top.continew.admin.tenant.service.TenantService; -import top.continew.starter.core.util.ExceptionUtils; -import top.continew.starter.core.util.validation.ValidationUtils; import top.continew.starter.extension.crud.annotation.CrudRequestMapping; import top.continew.starter.extension.crud.enums.Api; import top.continew.starter.extension.tenant.util.TenantUtils; @@ -61,10 +59,8 @@ public class TenantController extends BaseController { - String password = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(encryptPassword)); - ValidationUtils.throwIfNull(password, "新密码解密失败"); + String password = SecureUtils.decryptPasswordByRsaPrivateKey(req.getPassword(), "新密码解密失败"); userApi.resetPassword(password, tenant.getAdminUser()); }); } diff --git a/continew-system/src/main/java/top/continew/admin/auth/handler/AccountLoginHandler.java b/continew-system/src/main/java/top/continew/admin/auth/handler/AccountLoginHandler.java index 26c6cbe5..42235850 100644 --- a/continew-system/src/main/java/top/continew/admin/auth/handler/AccountLoginHandler.java +++ b/continew-system/src/main/java/top/continew/admin/auth/handler/AccountLoginHandler.java @@ -36,7 +36,6 @@ import top.continew.admin.system.enums.PasswordPolicyEnum; import top.continew.admin.system.model.entity.user.UserDO; import top.continew.admin.system.model.resp.ClientResp; import top.continew.starter.cache.redisson.util.RedisUtils; -import top.continew.starter.core.util.ExceptionUtils; import top.continew.starter.core.util.validation.CheckUtils; import top.continew.starter.core.util.validation.ValidationUtils; @@ -58,12 +57,11 @@ public class AccountLoginHandler extends AbstractLoginHandler { @Override public LoginResp login(AccountLoginReq req, ClientResp client, HttpServletRequest request) { // 解密密码 - String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getPassword())); - ValidationUtils.throwIfBlank(rawPassword, "密码解密失败"); + String password = SecureUtils.decryptPasswordByRsaPrivateKey(req.getPassword(), "密码解密失败"); // 验证用户名密码 String username = req.getUsername(); UserDO user = userService.getByUsername(username); - boolean isError = ObjectUtil.isNull(user) || !passwordEncoder.matches(rawPassword, user.getPassword()); + boolean isError = ObjectUtil.isNull(user) || !passwordEncoder.matches(password, user.getPassword()); // 检查账号锁定状态 this.checkUserLocked(req.getUsername(), request, isError); ValidationUtils.throwIf(isError, "用户名或密码不正确"); diff --git a/continew-system/src/main/java/top/continew/admin/system/api/TenantDataApiForSystemImpl.java b/continew-system/src/main/java/top/continew/admin/system/api/TenantDataApiForSystemImpl.java index 5d02da58..20d775d1 100644 --- a/continew-system/src/main/java/top/continew/admin/system/api/TenantDataApiForSystemImpl.java +++ b/continew-system/src/main/java/top/continew/admin/system/api/TenantDataApiForSystemImpl.java @@ -18,7 +18,6 @@ package top.continew.admin.system.api; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.collection.ListUtil; -import cn.hutool.core.util.ReUtil; import com.baomidou.mybatisplus.core.conditions.Wrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.RequiredArgsConstructor; @@ -28,7 +27,6 @@ import top.continew.admin.common.api.tenant.PackageMenuApi; import top.continew.admin.common.api.tenant.TenantApi; import top.continew.admin.common.api.tenant.TenantDataApi; import top.continew.admin.common.constant.GlobalConstants; -import top.continew.admin.common.constant.RegexConstants; import top.continew.admin.common.enums.DataScopeEnum; import top.continew.admin.common.enums.DisEnableStatusEnum; import top.continew.admin.common.enums.GenderEnum; @@ -47,8 +45,6 @@ import top.continew.admin.system.service.FileService; import top.continew.admin.system.service.RoleMenuService; import top.continew.admin.system.service.UserRoleService; import top.continew.starter.core.util.CollUtils; -import top.continew.starter.core.util.ExceptionUtils; -import top.continew.starter.core.util.validation.ValidationUtils; import top.continew.starter.extension.tenant.util.TenantUtils; import java.time.LocalDateTime; @@ -187,15 +183,12 @@ public class TenantDataApiForSystemImpl implements TenantDataApi { */ private Long initUserData(TenantDTO tenant, Long deptId) { // 解密密码 - String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(tenant.getPassword())); - ValidationUtils.throwIfNull(rawPassword, "密码解密失败"); - ValidationUtils.throwIf(!ReUtil - .isMatch(RegexConstants.PASSWORD, rawPassword), "密码长度为 8-32 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字"); + String password = SecureUtils.decryptPasswordByRsaPrivateKey(tenant.getPassword(), "密码解密失败", true); // 初始化用户 UserDO user = new UserDO(); user.setUsername(tenant.getUsername()); user.setNickname(RoleCodeEnum.TENANT_ADMIN.getDescription()); - user.setPassword(rawPassword); + user.setPassword(password); user.setGender(GenderEnum.UNKNOWN); user.setDescription("系统初始用户"); user.setStatus(DisEnableStatusEnum.ENABLE); diff --git a/continew-system/src/main/java/top/continew/admin/system/controller/UserController.java b/continew-system/src/main/java/top/continew/admin/system/controller/UserController.java index 10e6119e..c777cb93 100644 --- a/continew-system/src/main/java/top/continew/admin/system/controller/UserController.java +++ b/continew-system/src/main/java/top/continew/admin/system/controller/UserController.java @@ -17,7 +17,6 @@ package top.continew.admin.system.controller; import cn.dev33.satoken.annotation.SaCheckPermission; -import cn.hutool.core.util.ReUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.enums.ParameterIn; @@ -31,7 +30,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import top.continew.admin.common.base.controller.BaseController; -import top.continew.admin.common.constant.RegexConstants; import top.continew.admin.common.util.SecureUtils; import top.continew.admin.system.model.query.UserQuery; import top.continew.admin.system.model.req.user.UserImportReq; @@ -43,7 +41,6 @@ import top.continew.admin.system.model.resp.user.UserImportParseResp; import top.continew.admin.system.model.resp.user.UserImportResp; import top.continew.admin.system.model.resp.user.UserResp; import top.continew.admin.system.service.UserService; -import top.continew.starter.core.util.ExceptionUtils; import top.continew.starter.core.util.validation.ValidationUtils; import top.continew.starter.extension.crud.annotation.CrudRequestMapping; import top.continew.starter.extension.crud.enums.Api; @@ -68,11 +65,8 @@ public class UserController extends BaseController create(@RequestBody @Valid UserReq req) { - String rawPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getPassword())); - ValidationUtils.throwIfNull(rawPassword, "密码解密失败"); - ValidationUtils.throwIf(!ReUtil - .isMatch(RegexConstants.PASSWORD, rawPassword), "密码长度为 8-32 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字"); - req.setPassword(rawPassword); + String password = SecureUtils.decryptPasswordByRsaPrivateKey(req.getPassword(), "密码解密失败", true); + req.setPassword(password); return super.create(req); } @@ -103,11 +97,8 @@ public class UserController extends BaseController SecureUtils.decryptByRsaPrivateKey(req.getNewPassword())); - ValidationUtils.throwIfNull(rawNewPassword, "新密码解密失败"); - ValidationUtils.throwIf(!ReUtil - .isMatch(RegexConstants.PASSWORD, rawNewPassword), "密码长度为 8-32 个字符,支持大小写字母、数字、特殊字符,至少包含字母和数字"); - req.setNewPassword(rawNewPassword); + String newPassword = SecureUtils.decryptPasswordByRsaPrivateKey(req.getNewPassword(), "新密码解密失败", true); + req.setNewPassword(newPassword); baseService.resetPassword(req, id); } diff --git a/continew-system/src/main/java/top/continew/admin/system/controller/UserProfileController.java b/continew-system/src/main/java/top/continew/admin/system/controller/UserProfileController.java index deff3e28..b30d03e4 100644 --- a/continew-system/src/main/java/top/continew/admin/system/controller/UserProfileController.java +++ b/continew-system/src/main/java/top/continew/admin/system/controller/UserProfileController.java @@ -49,7 +49,6 @@ import top.continew.admin.system.service.UserSocialService; import top.continew.starter.cache.redisson.util.RedisUtils; import top.continew.starter.core.exception.BadRequestException; import top.continew.starter.core.util.CollUtils; -import top.continew.starter.core.util.ExceptionUtils; import top.continew.starter.core.util.validation.ValidationUtils; import java.io.IOException; @@ -91,41 +90,33 @@ public class UserProfileController { @Operation(summary = "修改密码", description = "修改用户登录密码") @PatchMapping("/password") public void updatePassword(@RequestBody @Valid UserPasswordUpdateReq updateReq) { - String rawOldPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq - .getOldPassword())); - ValidationUtils.throwIfNull(rawOldPassword, DECRYPT_FAILED); - String rawNewPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq - .getNewPassword())); - ValidationUtils.throwIfNull(rawNewPassword, "新密码解密失败"); - userService.updatePassword(rawOldPassword, rawNewPassword, UserContextHolder.getUserId()); + String oldPassword = SecureUtils.decryptPasswordByRsaPrivateKey(updateReq.getOldPassword(), DECRYPT_FAILED); + String newPassword = SecureUtils.decryptPasswordByRsaPrivateKey(updateReq.getNewPassword(), "新密码解密失败"); + userService.updatePassword(oldPassword, newPassword, UserContextHolder.getUserId()); } @Operation(summary = "修改手机号", description = "修改手机号") @PatchMapping("/phone") public void updatePhone(@RequestBody @Valid UserPhoneUpdateReq updateReq) { - String rawOldPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq - .getOldPassword())); - ValidationUtils.throwIfBlank(rawOldPassword, DECRYPT_FAILED); + String oldPassword = SecureUtils.decryptPasswordByRsaPrivateKey(updateReq.getOldPassword(), DECRYPT_FAILED); String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + updateReq.getPhone(); String captcha = RedisUtils.get(captchaKey); ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED); ValidationUtils.throwIfNotEqualIgnoreCase(updateReq.getCaptcha(), captcha, "验证码不正确"); RedisUtils.delete(captchaKey); - userService.updatePhone(updateReq.getPhone(), rawOldPassword, UserContextHolder.getUserId()); + userService.updatePhone(updateReq.getPhone(), oldPassword, UserContextHolder.getUserId()); } @Operation(summary = "修改邮箱", description = "修改用户邮箱") @PatchMapping("/email") public void updateEmail(@RequestBody @Valid UserEmailUpdateReq updateReq) { - String rawOldPassword = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(updateReq - .getOldPassword())); - ValidationUtils.throwIfBlank(rawOldPassword, DECRYPT_FAILED); + String oldPassword = SecureUtils.decryptPasswordByRsaPrivateKey(updateReq.getOldPassword(), DECRYPT_FAILED); String captchaKey = CacheConstants.CAPTCHA_KEY_PREFIX + updateReq.getEmail(); String captcha = RedisUtils.get(captchaKey); ValidationUtils.throwIfBlank(captcha, CAPTCHA_EXPIRED); ValidationUtils.throwIfNotEqualIgnoreCase(updateReq.getCaptcha(), captcha, "验证码不正确"); RedisUtils.delete(captchaKey); - userService.updateEmail(updateReq.getEmail(), rawOldPassword, UserContextHolder.getUserId()); + userService.updateEmail(updateReq.getEmail(), oldPassword, UserContextHolder.getUserId()); } @Operation(summary = "查询绑定的三方账号", description = "查询绑定的三方账号")