# db-cryptor-spring-boot-starter **Repository Path**: welsonmayun/db-cryptor-spring-boot-starter ## Basic Information - **Project Name**: db-cryptor-spring-boot-starter - **Description**: 这是一个用于数据库字段加解密的Spring Boot Starter,支持SM4和AES两种加解密算法,通过注解方式即可轻松实现数据库字段的自动加解密。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2025-06-05 - **Last Updated**: 2025-09-05 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # DB Cryptor Spring Boot Starter 一个用于数据库字段加解密的Spring Boot Starter,支持SM4和AES两种加解密算法。 ## 特性 - 支持SM4和AES两种加解密算法 - 支持通过注解方式标记需要加解密的字段 - 支持MyBatis自动拦截处理 - 支持MyBatis Plus的Wrapper方式以及对象类型入参和返回值的加解密 - 支持自定义扫描包路径 - 通过缓存机制和ASM字节码技术,提高性能 - 支持Java 8及以上版本 - 支持Spring Boot 2.x版本 - 支持多种加密模式(CBC、ECB、CFB、OFB、CTR、GCM等) - 支持多种密钥长度(SM4固定128位,AES支持128/192/256位) ## 快速开始 ### 1. 添加依赖 ```xml io.gitee.welson db-cryptor-spring-boot-starter 1.0.0 ``` ### 2. 配置属性 在`application.yml`中添加配置: ```yaml db: cryptor: enabled: true # 是否启用加解密功能,默认开启 algorithm: SM4 # 加解密算法类型:SM4或AES,默认为SM4 mode: CBC # 加解密模式,默认为CBC padding: PKCS7Padding # 填充模式,默认为PKCS7Padding key: your-key # 加密密钥 iv: your-iv # 加密向量,在CBC/CFB/OFB/CTR/GCM模式下需要 scan-packages: # 需要扫描的包路径列表 - com.your.package encrypt-cache: # 加密缓存配置 size: 100 expire-minutes: -1 # -1表示不过期 decrypt-cache: # 解密缓存配置 size: 1000000 expire-minutes: -1 # -1表示不过期 ``` ### 3. 使用注解 在需要加解密的字段上添加`@CryptField`注解: ```java public class User { @CryptField private String idCard; // 身份证号 @CryptField(operation = CryptField.CryptOperation.ENCRYPT) private String phone; // 手机号 @CryptField(operation = CryptField.CryptOperation.DECRYPT) private String address; // 地址 } ``` ### 4. 在Mapper方法上使用注解 ```java import annotation.com.welson.db.cryptor.CryptField; @Mapper public interface UserMapper { /** * 会自动对User中标记了@CryptField注解的字段进行解密 */ User selectById(@Param("id") String id); /** * 会自动对User中标记了@CryptField注解的字段进行加密 */ int insert(User user); /** * 会自动对phone字段进行加密 */ User selectByPhone(@CryptField @Param("phone") String phone); /** * 会自动对返回值进行解密 */ @CryptField(operation = CryptField.CryptOperation.DECRYPT) String selectPhoneById(@Param("id") String id); } ``` ### 5. 使用自定义Wrapper 框架提供了支持加密字段查询的Wrapper,可以方便地进行加密字段的查询和更新操作: #### 5.1 查询操作 ```java // 使用Lambda方式 EncryptLambdaQueryWrapper lambdaWrapper = new EncryptLambdaQueryWrapper() .select(User::getName) // 选择需要查询的字段 .encryptEq(User::getName, "系统"); // 加密字段等值查询 User user = userMapper.selectOne(lambdaWrapper); // 使用普通方式 EncryptQueryWrapper wrapper = new EncryptQueryWrapper() .select("name") .encryptEq("name", "系统"); User user = userMapper.selectOne(wrapper); ``` #### 5.2 更新操作 ```java // 使用Lambda方式 EncryptLambdaUpdateWrapper lambdaWrapper = new EncryptLambdaUpdateWrapper() .encryptSet(User::getName, "新名字"); // 加密字段更新 userMapper.update(null, lambdaWrapper); // 使用普通方式 EncryptUpdateWrapper wrapper = new EncryptUpdateWrapper() .encryptSet("name", "新名字"); userMapper.update(null, wrapper); ``` #### 5.3 支持的方法 Wrapper支持以下加密字段操作方法: - 等值查询:`encryptEq` - 不等值查询:`encryptNe` - IN查询:`encryptIn` - NOT IN查询:`encryptNotIn` - 字段更新:`encryptSet` #### 5.4 注意事项 1. 使用`select`方法时,实体类必须要有无参构造方法,否则会类型转换失败 2. 加密字段的查询值会自动进行加密处理 3. 查询结果中的加密字段会自动进行解密处理 4. 支持链式调用,可以组合多个条件 ### 6. 手动加密 对于一些无法通过注解自动加密的场景,可以使用`EncryptHandler`工具类进行手动加密: ```java // 单个值加密 String encryptedValue = (String) EncryptHandler.encrypt("需要加密的值"); // 集合加密 List values = Arrays.asList("值1", "值2", "值3"); List encryptedValues = (List) EncryptHandler.encryptCollection(values); ``` 使用场景示例: ```java // 1. 在Service层手动加密 @Service public class UserService { public void updateUserPhone(String userId, String newPhone) { // 手动加密手机号 String encryptedPhone = (String) EncryptHandler.encrypt(newPhone); userMapper.updatePhone(userId, encryptedPhone); } } // 2. 在Controller层手动加密 @RestController public class UserController { @PostMapping("/user/phone") public void updatePhone(@RequestParam String phone) { // 手动加密手机号 String encryptedPhone = (String) EncryptHandler.encrypt(phone); userService.updatePhone(encryptedPhone); } } // 3. 批量处理场景 @Service public class BatchService { public void batchUpdatePhones(List phones) { // 批量加密手机号 List encryptedPhones = (List) EncryptHandler.encryptCollection(phones); userMapper.batchUpdatePhones(encryptedPhones); } } ``` 注意事项: 1. `EncryptHandler.encrypt()`方法只支持String类型的加密 2. `EncryptHandler.encryptCollection()`方法只支持String类型集合的加密 3. 加密后的值会自动进行Base64编码 4. 加密使用的密钥和IV与配置文件中的配置保持一致 ## 配置说明 | 配置项 | 说明 | 默认值 | |-----------------------------------------|------------|--------------| | db.cryptor.enabled | 是否启用加解密功能 | true | | db.cryptor.algorithm | 加解密算法类型 | SM4 | | db.cryptor.mode | 加解密模式 | CBC | | db.cryptor.padding | 填充模式 | PKCS7Padding | | db.cryptor.key | 加密密钥 | 必填 | | db.cryptor.iv | 加密向量 | 在CBC/CFB/OFB/CTR/GCM模式下可选,其他模式不需要 | | db.cryptor.scan-packages | 需要扫描的包路径列表 | 必填 | | db.cryptor.encrypt-cache.size | 加密缓存大小配置 | 100 | | db.cryptor.encrypt-cache.expire-minutes | 加密缓存过期时间配置 | -1 | | db.cryptor.decrypt-cache.size | 解密缓存大小配置 | 1000000 | | db.cryptor.decrypt-cache.expire-minutes | 解密缓存过期时间配置 | -1 | ## 注意事项 1. 密钥和向量长度必须符合算法要求: - SM4:固定128位(16字节)密钥长度 - AES:支持128位(16字节)、192位(24字节)、256位(32字节)密钥长度 2. 扫描包路径必须配置,否则无法识别需要加解密的实体类 3. 建议在生产环境中使用安全的密钥和向量,不要使用默认值 4. 如果使用了缓存,请注意内存使用情况,适当调整缓存大小 5. 加密模式说明: - SM4算法: - 支持 CBC、ECB、CFB、OFB、CTR 模式 - CBC/CFB/OFB/CTR 模式需要 IV - ECB 模式不需要 IV,配置 iv 将被忽略 - AES算法: - 支持 CBC、ECB、CFB、OFB、CTR、GCM 等模式 - CBC/CFB/OFB/CTR/GCM 模式需要 IV - ECB 模式不需要 IV,配置 iv 将被忽略 - GCM 模式提供认证加密功能,更安全,但仅 AES 算法支持 6. IV长度说明: - AES和SM4的块大小都是固定的16字节(128位) - SM4算法: - CBC/OFB/CTR模式:IV长度必须等于块大小(16字节) - CFB模式:IV长度可以小于块大小,但默认使用块大小(16字节) - AES算法: - CBC/OFB/CTR模式:IV长度必须等于块大小(16字节) - CFB模式:IV长度可以小于块大小,但默认使用块大小(16字节) - GCM模式:IV长度通常为12字节(96位) - 如果配置了IV,系统会自动验证IV长度是否符合要求 7. 密钥长度说明: - SM4算法:固定使用128位(16字节)密钥长度 - AES算法:支持128位(16字节)、192位(24字节)、256位(32字节)密钥长度 - 默认使用128位密钥长度 - 使用AES-256时,需要安装JCE无限制权限策略文件 ## 版本要求 - Java 8+ - Spring Boot 2.x - MyBatis 3.x