mirror of
				https://github.com/continew-org/continew-admin.git
				synced 2025-10-31 22:57:17 +08:00 
			
		
		
		
	build: continew-starter 2.13.2-SNAPSHOT => 2.13.2
1.使用 EncryptHelper 重构用户导入相关加密查询场景 2.BCryptEncryptor 适配最新加密体系 3.使用 Jackson JSONUtils 优化 ServletUtils.writeJSON(Hutool JSONUtil 序列化无法识别 Jackson 注解) 4.DefaultDataPermissionUserDataProvider 包调整、UserData、RoleData 字段类型调整 5.其他隐形升级(租户拦截器优先级、依赖升级等)
This commit is contained in:
		| @@ -4,7 +4,7 @@ | |||||||
| <img src="https://img.shields.io/badge/SNAPSHOT-v4.0.0-%23ff3f59.svg" alt="Release" /> | <img src="https://img.shields.io/badge/SNAPSHOT-v4.0.0-%23ff3f59.svg" alt="Release" /> | ||||||
| </a> | </a> | ||||||
| <a href="https://github.com/continew-org/continew-starter" title="ContiNew Starter" target="_blank"> | <a href="https://github.com/continew-org/continew-starter" title="ContiNew Starter" target="_blank"> | ||||||
| <img src="https://img.shields.io/badge/ContiNew Starter-2.13.1-%236CB52D.svg" alt="ContiNew Starter" /> | <img src="https://img.shields.io/badge/ContiNew Starter-2.13.2-%236CB52D.svg" alt="ContiNew Starter" /> | ||||||
| </a> | </a> | ||||||
| <a href="https://spring.io/projects/spring-boot" title="Spring Boot" target="_blank"> | <a href="https://spring.io/projects/spring-boot" title="Spring Boot" target="_blank"> | ||||||
| <img src="https://img.shields.io/badge/Spring Boot-3.3.12-%236CB52D.svg?logo=Spring-Boot" alt="Spring Boot" /> | <img src="https://img.shields.io/badge/Spring Boot-3.3.12-%236CB52D.svg?logo=Spring-Boot" alt="Spring Boot" /> | ||||||
| @@ -226,7 +226,7 @@ public class DeptController extends BaseController<DeptService, DeptResp, DeptDe | |||||||
| | <a href="https://arco.design/vue/docs/start" target="_blank">Arco Design</a> | 2.57.0       | 字节跳动推出的前端 UI 框架,年轻化的色彩和组件设计。         | | | <a href="https://arco.design/vue/docs/start" target="_blank">Arco Design</a> | 2.57.0       | 字节跳动推出的前端 UI 框架,年轻化的色彩和组件设计。         | | ||||||
| | <a href="https://www.typescriptlang.org/zh/" target="_blank">TypeScript</a> | 5.0.4        | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 | | | <a href="https://www.typescriptlang.org/zh/" target="_blank">TypeScript</a> | 5.0.4        | TypeScript 是微软开发的一个开源的编程语言,通过在 JavaScript 的基础上添加静态类型定义构建而成。 | | ||||||
| | <a href="https://vite.dev/" target="_blank">Vite</a>         | 5.1.5        | 下一代的前端工具链,为开发提供极速响应。                     | | | <a href="https://vite.dev/" target="_blank">Vite</a>         | 5.1.5        | 下一代的前端工具链,为开发提供极速响应。                     | | ||||||
| | [ContiNew Starter](https://github.com/continew-org/continew-starter) | 2.13.1       | ContiNew Starter 包含了一系列经过企业实践优化的依赖包(如 MyBatis-Plus、SaToken),可轻松集成到应用中,为开发人员减少手动引入依赖及配置的麻烦,为 Spring Boot Web 项目的灵活快速构建提供支持。 | | | [ContiNew Starter](https://github.com/continew-org/continew-starter) | 2.13.2       | ContiNew Starter 包含了一系列经过企业实践优化的依赖包(如 MyBatis-Plus、SaToken),可轻松集成到应用中,为开发人员减少手动引入依赖及配置的麻烦,为 Spring Boot Web 项目的灵活快速构建提供支持。 | | ||||||
| | <a href="https://spring.io/projects/spring-boot" target="_blank">Spring Boot</a> | 3.3.12       | 简化 Spring 应用的初始搭建和开发过程,基于“约定优于配置”的理念,使开发人员不再需要定义样板化的配置。(Spring Boot 3.0 开始,要求 Java 17 作为最低版本) | | | <a href="https://spring.io/projects/spring-boot" target="_blank">Spring Boot</a> | 3.3.12       | 简化 Spring 应用的初始搭建和开发过程,基于“约定优于配置”的理念,使开发人员不再需要定义样板化的配置。(Spring Boot 3.0 开始,要求 Java 17 作为最低版本) | | ||||||
| | <a href="https://undertow.io/" target="_blank">Undertow</a>  | 2.3.18.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 | | | <a href="https://undertow.io/" target="_blank">Undertow</a>  | 2.3.18.Final | 采用 Java 开发的灵活的高性能 Web 服务器,提供包括阻塞和基于 NIO 的非堵塞机制。 | | ||||||
| | <a href="https://sa-token.dev33.cn/" target="_blank">Sa-Token + JWT</a> | 1.44.0       | 轻量级 Java 权限认证框架,让鉴权变得简单、优雅。             | | | <a href="https://sa-token.dev33.cn/" target="_blank">Sa-Token + JWT</a> | 1.44.0       | 轻量级 Java 权限认证框架,让鉴权变得简单、优雅。             | | ||||||
| @@ -248,7 +248,7 @@ public class DeptController extends BaseController<DeptService, DeptResp, DeptDe | |||||||
| | [AJ-Captcha](https://ajcaptcha.beliefteam.cn/captcha-doc/)   | 1.3.0        | Java 行为验证码,包含滑动拼图、文字点选两种方式,UI支持弹出和嵌入两种方式。 | | | [AJ-Captcha](https://ajcaptcha.beliefteam.cn/captcha-doc/)   | 1.3.0        | Java 行为验证码,包含滑动拼图、文字点选两种方式,UI支持弹出和嵌入两种方式。 | | ||||||
| | Easy Captcha                                                 | 1.6.2        | Java 图形验证码,支持 gif、中文、算术等类型,可用于 Java Web、JavaSE 等项目。 | | | Easy Captcha                                                 | 1.6.2        | Java 图形验证码,支持 gif、中文、算术等类型,可用于 Java Web、JavaSE 等项目。 | | ||||||
| | [Crane4j](https://createsequence.gitee.io/crane4j-doc/#/)    | 2.9.0        | 一个基于注解的,用于完成一切 “根据 A 的 key 值拿到 B,再把 B 的属性映射到 A” 这类需求的字段填充框架。 | | | [Crane4j](https://createsequence.gitee.io/crane4j-doc/#/)    | 2.9.0        | 一个基于注解的,用于完成一切 “根据 A 的 key 值拿到 B,再把 B 的属性映射到 A” 这类需求的字段填充框架。 | | ||||||
| | [SpEL Validator](https://spel-validator.sticki.cn/)          | 0.5.0-beta   | 基于 SpEL 的 jakarta.validation-api 扩展增强包。             | | | [SpEL Validator](https://spel-validator.sticki.cn/)          | 0.5.1-beta   | 基于 SpEL 的 jakarta.validation-api 扩展增强包。             | | ||||||
| | [CosID](https://cosid.ahoo.me/guide/getting-started.html)    | 2.13.0       | 旨在提供通用、灵活、高性能的分布式 ID 生成器。               | | | [CosID](https://cosid.ahoo.me/guide/getting-started.html)    | 2.13.0       | 旨在提供通用、灵活、高性能的分布式 ID 生成器。               | | ||||||
| | [Graceful Response](https://doc.feiniaojin.com/graceful-response/home.html) | 5.0.4-boot3  | 一个Spring Boot技术栈下的优雅响应处理组件,可以帮助开发者完成响应数据封装、异常处理、错误码填充等过程,提高开发效率,提高代码质量。 | | | [Graceful Response](https://doc.feiniaojin.com/graceful-response/home.html) | 5.0.4-boot3  | 一个Spring Boot技术栈下的优雅响应处理组件,可以帮助开发者完成响应数据封装、异常处理、错误码填充等过程,提高开发效率,提高代码质量。 | | ||||||
| | <a href="https://doc.xiaominfo.com/" target="_blank">Knife4j</a> | 4.5.0        | 前身是 swagger-bootstrap-ui,集 Swagger2 和 OpenAPI3 为一体的增强解决方案。 | | | <a href="https://doc.xiaominfo.com/" target="_blank">Knife4j</a> | 4.5.0        | 前身是 swagger-bootstrap-ui,集 Swagger2 和 OpenAPI3 为一体的增强解决方案。 | | ||||||
|   | |||||||
| @@ -17,7 +17,8 @@ | |||||||
| package top.continew.admin.common.config.mybatis; | package top.continew.admin.common.config.mybatis; | ||||||
|  |  | ||||||
| import org.springframework.security.crypto.password.PasswordEncoder; | import org.springframework.security.crypto.password.PasswordEncoder; | ||||||
| import top.continew.starter.security.crypto.encryptor.IEncryptor; | import top.continew.starter.security.crypto.encryptor.AbstractEncryptor; | ||||||
|  | import top.continew.starter.security.crypto.encryptor.CryptoContext; | ||||||
| import top.continew.starter.security.password.constant.PasswordEncoderConstants; | import top.continew.starter.security.password.constant.PasswordEncoderConstants; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -26,16 +27,17 @@ import top.continew.starter.security.password.constant.PasswordEncoderConstants; | |||||||
|  * @author Charles7c |  * @author Charles7c | ||||||
|  * @since 2024/2/8 22:29 |  * @since 2024/2/8 22:29 | ||||||
|  */ |  */ | ||||||
| public class BCryptEncryptor implements IEncryptor { | public class BCryptEncryptor extends AbstractEncryptor { | ||||||
|  |  | ||||||
|     private final PasswordEncoder passwordEncoder; |     private final PasswordEncoder passwordEncoder; | ||||||
|  |  | ||||||
|     public BCryptEncryptor(PasswordEncoder passwordEncoder) { |     public BCryptEncryptor(CryptoContext context, PasswordEncoder passwordEncoder) { | ||||||
|  |         super(context); | ||||||
|         this.passwordEncoder = passwordEncoder; |         this.passwordEncoder = passwordEncoder; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public String encrypt(String plaintext, String password, String publicKey) { |     public String encrypt(String plaintext) { | ||||||
|         // 如果已经是 BCrypt 加密格式,直接返回 |         // 如果已经是 BCrypt 加密格式,直接返回 | ||||||
|         if (PasswordEncoderConstants.BCRYPT_PATTERN.matcher(plaintext).matches()) { |         if (PasswordEncoderConstants.BCRYPT_PATTERN.matcher(plaintext).matches()) { | ||||||
|             return plaintext; |             return plaintext; | ||||||
| @@ -44,7 +46,7 @@ public class BCryptEncryptor implements IEncryptor { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     @Override |     @Override | ||||||
|     public String decrypt(String ciphertext, String password, String privateKey) { |     public String decrypt(String ciphertext) { | ||||||
|         return ciphertext; |         return ciphertext; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -16,14 +16,13 @@ | |||||||
|  |  | ||||||
| package top.continew.admin.common.config.mybatis; | package top.continew.admin.common.config.mybatis; | ||||||
|  |  | ||||||
| import cn.hutool.core.convert.Convert; |  | ||||||
| import top.continew.admin.common.context.UserContext; | import top.continew.admin.common.context.UserContext; | ||||||
| import top.continew.admin.common.context.UserContextHolder; | import top.continew.admin.common.context.UserContextHolder; | ||||||
| import top.continew.starter.core.util.CollUtils; | import top.continew.starter.core.util.CollUtils; | ||||||
| import top.continew.starter.extension.datapermission.enums.DataScope; | import top.continew.starter.extension.datapermission.enums.DataScope; | ||||||
| import top.continew.starter.extension.datapermission.filter.DataPermissionUserDataProvider; |  | ||||||
| import top.continew.starter.extension.datapermission.model.RoleData; | import top.continew.starter.extension.datapermission.model.RoleData; | ||||||
| import top.continew.starter.extension.datapermission.model.UserData; | import top.continew.starter.extension.datapermission.model.UserData; | ||||||
|  | import top.continew.starter.extension.datapermission.provider.DataPermissionUserDataProvider; | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 数据权限用户数据提供者 |  * 数据权限用户数据提供者 | ||||||
| @@ -42,10 +41,11 @@ public class DefaultDataPermissionUserDataProvider implements DataPermissionUser | |||||||
|     public UserData getUserData() { |     public UserData getUserData() { | ||||||
|         UserContext userContext = UserContextHolder.getContext(); |         UserContext userContext = UserContextHolder.getContext(); | ||||||
|         UserData userData = new UserData(); |         UserData userData = new UserData(); | ||||||
|         userData.setUserId(Convert.toStr(userContext.getId())); |         userData.setUserId(userContext.getId()); | ||||||
|         userData.setDeptId(Convert.toStr(userContext.getDeptId())); |         userData.setDeptId(userContext.getDeptId()); | ||||||
|         userData.setRoles(CollUtils.mapToSet(userContext.getRoles(), r -> new RoleData(Convert.toStr(r |         userData.setRoles(CollUtils.mapToSet(userContext.getRoles(), r -> new RoleData(r.getId(), DataScope.valueOf(r | ||||||
|             .getId()), DataScope.valueOf(r.getDataScope().name())))); |             .getDataScope() | ||||||
|  |             .name())))); | ||||||
|         return userData; |         return userData; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -22,7 +22,7 @@ import com.baomidou.mybatisplus.extension.parser.cache.JdkSerialCaffeineJsqlPars | |||||||
| import org.springframework.context.annotation.Bean; | import org.springframework.context.annotation.Bean; | ||||||
| import org.springframework.context.annotation.Configuration; | import org.springframework.context.annotation.Configuration; | ||||||
| import org.springframework.security.crypto.password.PasswordEncoder; | import org.springframework.security.crypto.password.PasswordEncoder; | ||||||
| import top.continew.starter.extension.datapermission.filter.DataPermissionUserDataProvider; | import top.continew.starter.extension.datapermission.provider.DataPermissionUserDataProvider; | ||||||
|  |  | ||||||
| import java.util.concurrent.TimeUnit; | import java.util.concurrent.TimeUnit; | ||||||
|  |  | ||||||
| @@ -62,6 +62,6 @@ public class MybatisPlusConfiguration { | |||||||
|      */ |      */ | ||||||
|     @Bean |     @Bean | ||||||
|     public BCryptEncryptor bCryptEncryptor(PasswordEncoder passwordEncoder) { |     public BCryptEncryptor bCryptEncryptor(PasswordEncoder passwordEncoder) { | ||||||
|         return new BCryptEncryptor(passwordEncoder); |         return new BCryptEncryptor(null, passwordEncoder); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -19,16 +19,8 @@ package top.continew.admin.common.util; | |||||||
| import cn.hutool.core.codec.Base64; | import cn.hutool.core.codec.Base64; | ||||||
| import cn.hutool.crypto.SecureUtil; | import cn.hutool.crypto.SecureUtil; | ||||||
| import cn.hutool.crypto.asymmetric.KeyType; | import cn.hutool.crypto.asymmetric.KeyType; | ||||||
| import cn.hutool.extra.spring.SpringUtil; |  | ||||||
| import top.continew.admin.common.config.RsaProperties; | import top.continew.admin.common.config.RsaProperties; | ||||||
| import top.continew.starter.core.exception.BusinessException; |  | ||||||
| import top.continew.starter.core.util.CollUtils; |  | ||||||
| import top.continew.starter.core.util.validation.ValidationUtils; | import top.continew.starter.core.util.validation.ValidationUtils; | ||||||
| import top.continew.starter.security.crypto.autoconfigure.CryptoProperties; |  | ||||||
| import top.continew.starter.security.crypto.encryptor.AesEncryptor; |  | ||||||
| import top.continew.starter.security.crypto.encryptor.IEncryptor; |  | ||||||
|  |  | ||||||
| import java.util.List; |  | ||||||
|  |  | ||||||
| /** | /** | ||||||
|  * 加密/解密工具类 |  * 加密/解密工具类 | ||||||
| @@ -86,22 +78,4 @@ public class SecureUtils { | |||||||
|     public static String decryptByRsaPrivateKey(String data, String privateKey) { |     public static String decryptByRsaPrivateKey(String data, String privateKey) { | ||||||
|         return new String(SecureUtil.rsa(privateKey, null).decrypt(Base64.decode(data), KeyType.PrivateKey)); |         return new String(SecureUtil.rsa(privateKey, null).decrypt(Base64.decode(data), KeyType.PrivateKey)); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |  | ||||||
|      * 对普通加密字段列表进行AES加密,优化starter加密模块后优化这个方法 |  | ||||||
|      * |  | ||||||
|      * @param values 待加密内容 |  | ||||||
|      * @return 加密后内容 |  | ||||||
|      */ |  | ||||||
|     public static List<String> encryptFieldByAes(List<String> values) { |  | ||||||
|         IEncryptor encryptor = new AesEncryptor(); |  | ||||||
|         CryptoProperties properties = SpringUtil.getBean(CryptoProperties.class); |  | ||||||
|         return CollUtils.mapToList(values, value -> { |  | ||||||
|             try { |  | ||||||
|                 return encryptor.encrypt(value, properties.getPassword(), properties.getPublicKey()); |  | ||||||
|             } catch (Exception e) { |  | ||||||
|                 throw new BusinessException("字段加密异常"); |  | ||||||
|             } |  | ||||||
|         }); |  | ||||||
|     } |  | ||||||
| } | } | ||||||
|   | |||||||
| @@ -28,6 +28,7 @@ import top.continew.admin.common.context.UserContext; | |||||||
| import top.continew.admin.common.context.UserContextHolder; | import top.continew.admin.common.context.UserContextHolder; | ||||||
| import top.continew.starter.core.util.ServletUtils; | import top.continew.starter.core.util.ServletUtils; | ||||||
| import top.continew.starter.extension.tenant.context.TenantContextHolder; | import top.continew.starter.extension.tenant.context.TenantContextHolder; | ||||||
|  | import top.continew.starter.json.jackson.util.JSONUtils; | ||||||
| import top.continew.starter.web.model.R; | import top.continew.starter.web.model.R; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -61,7 +62,8 @@ public class SaExtensionInterceptor extends SaInterceptor { | |||||||
|             Long userTenantId = userContext.getTenantId(); |             Long userTenantId = userContext.getTenantId(); | ||||||
|             Long tenantId = TenantContextHolder.getTenantId(); |             Long tenantId = TenantContextHolder.getTenantId(); | ||||||
|             if (!userTenantId.equals(tenantId)) { |             if (!userTenantId.equals(tenantId)) { | ||||||
|                 ServletUtils.writeJSON(response, R.fail(String.valueOf(HttpStatus.FORBIDDEN.value()), "您当前没有访问该租户的权限")); |                 R r = R.fail(String.valueOf(HttpStatus.FORBIDDEN.value()), "您当前没有访问该租户的权限"); | ||||||
|  |                 ServletUtils.writeJSON(response, JSONUtils.toJsonStr(r)); | ||||||
|                 return false; |                 return false; | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -123,6 +123,8 @@ logging: | |||||||
| continew-starter.security: | continew-starter.security: | ||||||
|   crypto: |   crypto: | ||||||
|     enabled: true |     enabled: true | ||||||
|  |     # 默认算法,即 @FieldEncrypt 默认采用的算法(默认:AES 对称加密算法) | ||||||
|  |     algorithm: AES | ||||||
|     # 对称加密算法密钥 |     # 对称加密算法密钥 | ||||||
|     password: abcdefghijklmnop |     password: abcdefghijklmnop | ||||||
|     # 非对称加密算法密钥(在线生成 RSA 密钥对:http://web.chacuo.net/netrsakeypair) |     # 非对称加密算法密钥(在线生成 RSA 密钥对:http://web.chacuo.net/netrsakeypair) | ||||||
|   | |||||||
| @@ -132,6 +132,8 @@ logging: | |||||||
| continew-starter.security: | continew-starter.security: | ||||||
|   crypto: |   crypto: | ||||||
|     enabled: true |     enabled: true | ||||||
|  |     # 默认算法,即 @FieldEncrypt 默认采用的算法(默认:AES 对称加密算法) | ||||||
|  |     algorithm: AES | ||||||
|     # 对称加密算法密钥 |     # 对称加密算法密钥 | ||||||
|     password: abcdefghijklmnop |     password: abcdefghijklmnop | ||||||
|     # 非对称加密算法密钥(在线生成 RSA 密钥对:http://web.chacuo.net/netrsakeypair) |     # 非对称加密算法密钥(在线生成 RSA 密钥对:http://web.chacuo.net/netrsakeypair) | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ application: | |||||||
|   description: 持续迭代优化的前后端分离中后台管理系统框架,开箱即用,持续提供舒适的开发体验。 |   description: 持续迭代优化的前后端分离中后台管理系统框架,开箱即用,持续提供舒适的开发体验。 | ||||||
|   # 版本 |   # 版本 | ||||||
|   version: 4.0.0-SNAPSHOT |   version: 4.0.0-SNAPSHOT | ||||||
|   starter: 2.13.1 |   starter: 2.13.2 | ||||||
|   # 基本包 |   # 基本包 | ||||||
|   base-package: top.continew.admin |   base-package: top.continew.admin | ||||||
|   ## 作者信息配置 |   ## 作者信息配置 | ||||||
|   | |||||||
| @@ -176,14 +176,16 @@ VALUES | |||||||
| (1, 'admin', '系统管理员', '{bcrypt}$2a$10$4jGwK2BMJ7FgVR.mgwGodey8.xR8FLoU1XSXpxJ9nZQt.pufhasSa', 1, '42190c6c5639d2ca4edb4150a35e058559ccf8270361a23745a2fd285a273c28', '5bda89a4609a65546422ea56bfe5eab4', NULL, '系统初始用户', 1, b'1', NOW(), 1, 1, NOW()), | (1, 'admin', '系统管理员', '{bcrypt}$2a$10$4jGwK2BMJ7FgVR.mgwGodey8.xR8FLoU1XSXpxJ9nZQt.pufhasSa', 1, '42190c6c5639d2ca4edb4150a35e058559ccf8270361a23745a2fd285a273c28', '5bda89a4609a65546422ea56bfe5eab4', NULL, '系统初始用户', 1, b'1', NOW(), 1, 1, NOW()), | ||||||
| (547889293968801822, 'test', '测试员', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 2, NULL, NULL, NULL, NULL, 1, b'0', NOW(), 547887852587843593, 1, NOW()), | (547889293968801822, 'test', '测试员', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 2, NULL, NULL, NULL, NULL, 1, b'0', NOW(), 547887852587843593, 1, NOW()), | ||||||
| (547889293968801823, 'Charles', 'Charles', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '代码写到极致,就是艺术。', 1, b'0', NOW(), 547887852587843595, 1, NOW()), | (547889293968801823, 'Charles', 'Charles', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '代码写到极致,就是艺术。', 1, b'0', NOW(), 547887852587843595, 1, NOW()), | ||||||
| (547889293968801824, 'Yoofff', 'Yoofff', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '弱小和无知不是生存的障碍,傲慢才是。', 1, b'0', NOW(), 1, 1, NOW()), | (547889293968801824, 'Yoofff', 'Yoofff', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '弱小和无知不是生存的障碍,傲慢才是。', 2, b'0', NOW(), 1, 1, NOW()), | ||||||
| (547889293968801825, 'Jasmine', 'Jasmine', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '干就完事了!', 1, b'0', NOW(), 547887852587843605, 1, NOW()), | (547889293968801825, 'Jasmine', 'Jasmine', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '干就完事了!', 1, b'0', NOW(), 547887852587843605, 1, NOW()), | ||||||
| (547889293968801826, 'AutumnSail', '秋登', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '只有追求完美,才能创造奇迹。', 1, b'0', NOW(), 547887852587843602, 1, NOW()), | (547889293968801826, 'AutumnSail', '秋登', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '只有追求完美,才能创造奇迹。', 1, b'0', NOW(), 547887852587843602, 1, NOW()), | ||||||
| (547889293968801827, 'Kils', 'Kils', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '可以摆烂,但不能真的菜。', 1, b'0', NOW(), 547887852587843599, 1, NOW()), | (547889293968801827, 'Kils', 'Kils', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '可以摆烂,但不能真的菜。', 1, b'0', NOW(), 547887852587843599, 1, NOW()), | ||||||
| (547889293968801828, 'mochou', '莫愁', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '万事莫愁,皆得所愿。', 1, b'0', NOW(), 547887852587843602, 1, NOW()), | (547889293968801828, 'mochou', '莫愁', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '万事莫愁,皆得所愿。', 1, b'0', NOW(), 547887852587843602, 1, NOW()), | ||||||
| (547889293968801829, 'Jing', 'MS-Jing', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '路虽远,行则将至。', 2, b'0', NOW(), 547887852587843599, 1, NOW()), | (547889293968801829, 'Jing', 'MS-Jing', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '路虽远,行则将至。', 2, b'0', NOW(), 547887852587843599, 1, NOW()), | ||||||
| (547889293968801830, 'domw', '梓陌', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '胜利是奖赏,挫折是常态。', 1, b'0', NOW(), 547887852587843608, 1, NOW()), | (547889293968801830, 'domw', '梓陌', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '胜利是奖赏,挫折是常态。', 1, b'0', NOW(), 547887852587843608, 1, NOW()), | ||||||
| (547889293968801831, 'xtanyu', '小熊', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '不想上班。', 1, b'0', NOW(), 547887852587843611, 1, NOW()); | (547889293968801831, 'xtanyu', '小熊', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '不想上班。', 1, b'0', NOW(), 547887852587843611, 1, NOW()), | ||||||
|  | (547889293968801832, 'luoqiz', '老罗', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '行者无疆,丈量四方。', 1, b'0', NOW(), 1, 1, NOW()), | ||||||
|  | (547889293968801833, 'lishuyanla', '颜如玉', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '书中自有颜如玉,世间多是李莫愁。', 1, b'0', NOW(), 1, 1, NOW()); | ||||||
|  |  | ||||||
| -- 初始化默认参数 | -- 初始化默认参数 | ||||||
| INSERT INTO `sys_option` | INSERT INTO `sys_option` | ||||||
| @@ -246,7 +248,9 @@ VALUES | |||||||
| (8, 547889293968801828, 547888897925840928), | (8, 547889293968801828, 547888897925840928), | ||||||
| (9, 547889293968801829, 547888897925840928), | (9, 547889293968801829, 547888897925840928), | ||||||
| (10, 547889293968801830, 547888897925840928), | (10, 547889293968801830, 547888897925840928), | ||||||
| (11, 547889293968801831, 547888897925840928); | (11, 547889293968801831, 547888897925840928), | ||||||
|  | (12, 547889293968801832, 547888897925840928), | ||||||
|  | (13, 547889293968801833, 547888897925840928); | ||||||
|  |  | ||||||
| -- 初始化默认角色和菜单关联数据 | -- 初始化默认角色和菜单关联数据 | ||||||
| INSERT INTO `sys_role_menu` | INSERT INTO `sys_role_menu` | ||||||
|   | |||||||
| @@ -183,7 +183,9 @@ VALUES | |||||||
| (547889293968801828, 'mochou', '莫愁', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '万事莫愁,皆得所愿。', 1, false, NOW(), 547887852587843602, 1, NOW()), | (547889293968801828, 'mochou', '莫愁', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '万事莫愁,皆得所愿。', 1, false, NOW(), 547887852587843602, 1, NOW()), | ||||||
| (547889293968801829, 'Jing', 'MS-Jing', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '路虽远,行则将至。', 2, false, NOW(), 547887852587843599, 1, NOW()), | (547889293968801829, 'Jing', 'MS-Jing', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '路虽远,行则将至。', 2, false, NOW(), 547887852587843599, 1, NOW()), | ||||||
| (547889293968801830, 'domw', '梓陌', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '胜利是奖赏,挫折是常态。', 1, false, NOW(), 547887852587843608, 1, NOW()), | (547889293968801830, 'domw', '梓陌', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '胜利是奖赏,挫折是常态。', 1, false, NOW(), 547887852587843608, 1, NOW()), | ||||||
| (547889293968801831, 'xtanyu', '小熊', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '不想上班。', 1, false, NOW(), 547887852587843611, 1, NOW()); | (547889293968801831, 'xtanyu', '小熊', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '不想上班。', 1, false, NOW(), 547887852587843611, 1, NOW()), | ||||||
|  | (547889293968801832, 'luoqiz', '老罗', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '行者无疆,丈量四方。', 1, false, NOW(), 1, 1, NOW()), | ||||||
|  | (547889293968801833, 'lishuyanla', '颜如玉', '{bcrypt}$2a$10$xAsoeMJ.jc/kSxhviLAg7.j2iFrhi6yYAdniNdjLiIUWU/BRZl2Ti', 1, NULL, NULL, NULL, '书中自有颜如玉,世间多是李莫愁。', 1, false, NOW(), 1, 1, NOW()); | ||||||
|  |  | ||||||
| -- 初始化默认参数 | -- 初始化默认参数 | ||||||
| INSERT INTO "sys_option" | INSERT INTO "sys_option" | ||||||
| @@ -246,7 +248,9 @@ VALUES | |||||||
| (8, 547889293968801828, 547888897925840928), | (8, 547889293968801828, 547888897925840928), | ||||||
| (9, 547889293968801829, 547888897925840928), | (9, 547889293968801829, 547888897925840928), | ||||||
| (10, 547889293968801830, 547888897925840928), | (10, 547889293968801830, 547888897925840928), | ||||||
| (11, 547889293968801831, 547888897925840928); | (11, 547889293968801831, 547888897925840928), | ||||||
|  | (12, 547889293968801832, 547888897925840928), | ||||||
|  | (13, 547889293968801833, 547888897925840928); | ||||||
|  |  | ||||||
| -- 初始化默认角色和菜单关联数据 | -- 初始化默认角色和菜单关联数据 | ||||||
| INSERT INTO "sys_role_menu" | INSERT INTO "sys_role_menu" | ||||||
|   | |||||||
| @@ -83,4 +83,10 @@ public class DeptResp extends BaseDetailResp { | |||||||
|     @Schema(description = "描述", example = "测试部描述信息") |     @Schema(description = "描述", example = "测试部描述信息") | ||||||
|     @ExcelProperty(value = "描述", order = 8) |     @ExcelProperty(value = "描述", order = 8) | ||||||
|     private String description; |     private String description; | ||||||
|  |  | ||||||
|  |     // TODO 临时修复,等待 ContiNew Starter 2.13.3 发布移除 | ||||||
|  |     @Override | ||||||
|  |     public Long getId() { | ||||||
|  |         return super.getId(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -122,4 +122,10 @@ public class MenuResp extends BaseResp { | |||||||
|      */ |      */ | ||||||
|     @Schema(description = "状态", example = "1") |     @Schema(description = "状态", example = "1") | ||||||
|     private DisEnableStatusEnum status; |     private DisEnableStatusEnum status; | ||||||
|  |  | ||||||
|  |     // TODO 临时修复,等待 ContiNew Starter 2.13.3 发布移除 | ||||||
|  |     @Override | ||||||
|  |     public Long getId() { | ||||||
|  |         return super.getId(); | ||||||
|  |     } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -63,7 +63,6 @@ import top.continew.admin.common.context.UserContextHolder; | |||||||
| import top.continew.admin.common.enums.DisEnableStatusEnum; | import top.continew.admin.common.enums.DisEnableStatusEnum; | ||||||
| import top.continew.admin.common.enums.GenderEnum; | import top.continew.admin.common.enums.GenderEnum; | ||||||
| import top.continew.admin.common.service.CommonUserService; | import top.continew.admin.common.service.CommonUserService; | ||||||
| import top.continew.admin.common.util.SecureUtils; |  | ||||||
| import top.continew.admin.system.enums.OptionCategoryEnum; | import top.continew.admin.system.enums.OptionCategoryEnum; | ||||||
| import top.continew.admin.system.mapper.user.UserMapper; | import top.continew.admin.system.mapper.user.UserMapper; | ||||||
| import top.continew.admin.system.model.entity.DeptDO; | import top.continew.admin.system.model.entity.DeptDO; | ||||||
| @@ -86,6 +85,7 @@ import top.continew.starter.core.util.validation.CheckUtils; | |||||||
| import top.continew.starter.extension.crud.model.query.PageQuery; | import top.continew.starter.extension.crud.model.query.PageQuery; | ||||||
| import top.continew.starter.extension.crud.model.query.SortQuery; | import top.continew.starter.extension.crud.model.query.SortQuery; | ||||||
| import top.continew.starter.extension.crud.model.resp.PageResp; | import top.continew.starter.extension.crud.model.resp.PageResp; | ||||||
|  | import top.continew.starter.security.crypto.utils.EncryptHelper; | ||||||
|  |  | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.time.Duration; | import java.time.Duration; | ||||||
| @@ -285,13 +285,13 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes | |||||||
|  |  | ||||||
|         // 查询重复用户 |         // 查询重复用户 | ||||||
|         userImportResp |         userImportResp | ||||||
|             .setDuplicateUserRows(countExistByField(validRowList, UserImportRowReq::getUsername, UserDO::getUsername, false)); |             .setDuplicateUserRows(countExistByField(validRowList, UserImportRowReq::getUsername, UserDO::getUsername)); | ||||||
|         // 查询重复邮箱 |         // 查询重复邮箱 | ||||||
|         userImportResp |         userImportResp.setDuplicateEmailRows(countExistByField(validRowList, row -> EncryptHelper.encrypt(row | ||||||
|             .setDuplicateEmailRows(countExistByField(validRowList, UserImportRowReq::getEmail, UserDO::getEmail, true)); |             .getEmail()), UserDO::getEmail)); | ||||||
|         // 查询重复手机 |         // 查询重复手机 | ||||||
|         userImportResp |         userImportResp.setDuplicatePhoneRows(countExistByField(validRowList, row -> EncryptHelper.encrypt(row | ||||||
|             .setDuplicatePhoneRows(countExistByField(validRowList, UserImportRowReq::getPhone, UserDO::getPhone, true)); |             .getPhone()), UserDO::getPhone)); | ||||||
|  |  | ||||||
|         // 设置导入会话并缓存数据,有效期10分钟 |         // 设置导入会话并缓存数据,有效期10分钟 | ||||||
|         String importKey = UUID.fastUUID().toString(true); |         String importKey = UUID.fastUUID().toString(true); | ||||||
| @@ -315,8 +315,10 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes | |||||||
|             throw new BusinessException("导入已过期,请重新上传"); |             throw new BusinessException("导入已过期,请重新上传"); | ||||||
|         } |         } | ||||||
|         // 已存在数据查询 |         // 已存在数据查询 | ||||||
|         List<String> existEmails = listExistByField(importUserList, UserImportRowReq::getEmail, UserDO::getEmail); |         List<String> existEmails = listExistByField(importUserList, row -> EncryptHelper.encrypt(row | ||||||
|         List<String> existPhones = listExistByField(importUserList, UserImportRowReq::getPhone, UserDO::getPhone); |             .getEmail()), UserDO::getEmail); | ||||||
|  |         List<String> existPhones = listExistByField(importUserList, row -> EncryptHelper.encrypt(row | ||||||
|  |             .getPhone()), UserDO::getPhone); | ||||||
|         List<UserDO> existUserList = listByUsernames(CollUtils |         List<UserDO> existUserList = listByUsernames(CollUtils | ||||||
|             .mapToList(importUserList, UserImportRowReq::getUsername)); |             .mapToList(importUserList, UserImportRowReq::getUsername)); | ||||||
|         List<String> existUsernames = CollUtils.mapToList(existUserList, UserDO::getUsername); |         List<String> existUsernames = CollUtils.mapToList(existUserList, UserDO::getUsername); | ||||||
| @@ -597,14 +599,12 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes | |||||||
|      */ |      */ | ||||||
|     private int countExistByField(List<UserImportRowReq> userRowList, |     private int countExistByField(List<UserImportRowReq> userRowList, | ||||||
|                                   Function<UserImportRowReq, String> rowField, |                                   Function<UserImportRowReq, String> rowField, | ||||||
|                                   SFunction<UserDO, ?> dbField, |                                   SFunction<UserDO, ?> dbField) { | ||||||
|                                   boolean fieldEncrypt) { |  | ||||||
|         List<String> fieldValues = CollUtils.mapToList(userRowList, rowField); |         List<String> fieldValues = CollUtils.mapToList(userRowList, rowField); | ||||||
|         if (fieldValues.isEmpty()) { |         if (fieldValues.isEmpty()) { | ||||||
|             return 0; |             return 0; | ||||||
|         } |         } | ||||||
|         return (int)this.count(Wrappers.<UserDO>lambdaQuery() |         return Math.toIntExact(baseMapper.lambdaQuery().in(dbField, fieldValues).count()); | ||||||
|             .in(dbField, fieldEncrypt ? SecureUtils.encryptFieldByAes(fieldValues) : fieldValues)); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -622,9 +622,7 @@ public class UserServiceImpl extends BaseServiceImpl<UserMapper, UserDO, UserRes | |||||||
|         if (fieldValues.isEmpty()) { |         if (fieldValues.isEmpty()) { | ||||||
|             return Collections.emptyList(); |             return Collections.emptyList(); | ||||||
|         } |         } | ||||||
|         List<UserDO> userList = baseMapper.selectList(Wrappers.<UserDO>lambdaQuery() |         List<UserDO> userList = baseMapper.lambdaQuery().select(dbField).in(dbField, fieldValues).list(); | ||||||
|             .in(dbField, SecureUtils.encryptFieldByAes(fieldValues)) |  | ||||||
|             .select(dbField)); |  | ||||||
|         return CollUtils.mapToList(userList, dbField); |         return CollUtils.mapToList(userList, dbField); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								pom.xml
									
									
									
									
									
								
							| @@ -13,7 +13,7 @@ | |||||||
|     <parent> |     <parent> | ||||||
|         <groupId>top.continew.starter</groupId> |         <groupId>top.continew.starter</groupId> | ||||||
|         <artifactId>continew-starter</artifactId> |         <artifactId>continew-starter</artifactId> | ||||||
|         <version>2.13.2-SNAPSHOT</version> |         <version>2.13.2</version> | ||||||
|     </parent> |     </parent> | ||||||
|  |  | ||||||
|     <groupId>top.continew.admin</groupId> |     <groupId>top.continew.admin</groupId> | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user