# 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