# data-desensitized
**Repository Path**: shellay/data-desensitized
## Basic Information
- **Project Name**: data-desensitized
- **Description**: 解决系统中数据安全问题,可以对Json类型的请求做数据脱敏及针对日志内容做数据脱敏。可自定义敏感信息,对原系统侵入性较小,提供多种可扩展方法。
- **Primary Language**: Java
- **License**: Apache-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 1
- **Forks**: 0
- **Created**: 2022-07-20
- **Last Updated**: 2023-09-19
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
### 数据脱敏(DD-desensitized data)
#### 背景
伴随着技术的发展,互联网的触角已经融入到生活中的每个角落,各种各样的App记录着我们的日常生活点滴。经历过技术的野蛮生长,个人信息满天飞的时代,诈骗、勒索等犯罪事件越来普遍,随之而来的是人们对隐私和信息安全的呼声越来越强烈。
在系统中,人的行为可以理解成`"人对资源的操作"`,就期目标而言,信息安全可以分成两个层次:
- 操作层面
> 操作的动作,如:查询,修改,添加,删除等。
- 数据安全
> 操作的资源,各种各样的信息数据,如,个人电话、住址等信息
#### 目标
本项目属于数据安全层面的一个补充,通过对敏感信息加密,即便数据泄露后,敏感数据信息不可读,减少因数据泄露而产生的负面影响。
#### 软件介绍
软件以SpringBoot为技术基础,从API和日志两层面对敏感数据进行加密脱敏。核心设计思想是在Json与对象间转换时,对敏感内容进行干预,**注意**本软件是基于`Jackson`进行设计。
- API:
> Restful风格且基于Json的API,在序列化与序列化过程中对指定的敏感信息进行编码与解码。
- 日志
> 日志基于log4j,对日志中的敏感内容进行编码脱敏。
#### 使用说明
##### 初始配置
1. Maven依赖
```xml
com.yy.tech.data
desensitized-data
1.0-SNAPSHOT
```
2. 在Application或是Configuration类上加注解`@EnableDesensitization`,或是`@ComponentScan`把包扫描到SpringBean容器中。如:
```java
@SpringBootApplication
@EnableDesensitization
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
```
3. 本软件提供了一个默认的Bean`desensitizeObjectMapper`,如果已有自定义的`ObjectMapper`,可以调用`DesensitizeHelper.help(ObjectMapper mapper)`方法,为`ObjectMapper`追加脱敏相关配置。
```java
@Configuration
@ComponentScan
@ConditionalOnProperty(value = SecretContent.KEY_DESENSITIZE_ENABLE,havingValue = "true")
public class DesensitizedConfiguration {
@Autowired
private DesensitizeHelper helper;
@Bean(SecretContent.DESENSITIZE_OBJECT_MAPPER)
@ConditionalOnMissingBean(name = SecretContent.DESENSITIZE_OBJECT_MAPPER)
public ObjectMapper desensitizeObjectMapper(){
return helper.help();
}
}
```
*如果没有生效,可能需要为`HttpMessageConverter`手动设置一下`ObjectMapper`。*
##### 自定义敏感规则
1. 注解方式
- @SecretProperty
> 在Restful API中,对Request或是Response中的敏感内容加上该注解,在请求过程中会对该属性进行编码和解码。可在SecretProperty指定`Encoder`和`Decoder`.
- @SecretParam
> 在Restful API中,主要用于对URL中的参数进行解码。
2. Json文件方式
> 支持通过配置方式配置脱敏规则。具体配置属性可参见`SecretRules`和`SecretRule`.
3. 环境变量方式
> 可以通过环境变量配置脱敏规则。
#### Example
*完整示例可参见`desensitized-app`*
##### 测试API
- 基于Bean实体
URI:
>`{{host}}/data/demo/bean`
Request:
```json
{
"title": "desensitized",
"employee": {
"name": "test1",
"idType": "sfz",
"idNumber": "111333532524525",
"email": "example@tech.com",
"phone": "18801233210"
}
}
```
Response:
```json
{
"employee": {
"name": "test1",
"birthdate": null,
"idType": "{AES}bxjufniPS4dJSzntcDIkzw==",
"idNumber": "{AES}Je/0qCbn2oF87WjyEjJwKQ==",
"phone": "18801233210",
"address": null,
"updateTime": null
}
}
```
- 基于Map
URI:
> {{host}}/data/demo/map
Request:
```json
{
"title": "desensitized",
"employee": {
"name": "test1",
"idType": "sfz",
"idNumber": "111333532524525",
"email": "example@tech.com",
"phone": "18801233210"
}
}
```
Response:
```json
{
"title": "desensitized",
"employee": {
"name": "test1",
"idType": "{AES}bxjufniPS4dJSzntcDIkzw==",
"idNumber": "111333532524525",
"email": "example@tech.com",
"phone": "18801233210"
},
"employeeId": -7760358248143830538,
"idNumber": "310122199907121234",
"updateTime": "2022-08-24 21:34:46"
}
```
- 基于参数
URI:
> {{host}}/data/demo/para/{AES}bxjufniPS4dJSzntcDIkzw==
Response:
```json
{
"employee": {
"name": "Example path variable",
"birthdate": "1999-03-12",
"idType": "{AES}muV/ZmvmHc7Q4lh/JDT6MQ==",
"idNumber": "{AES}bxjufniPS4dJSzntcDIkzw==",
"phone": "18817881788",
"address": null,
"updateTime": "2022-09-21 21:41:08"
}
}
```
##### 相关配置
1、环境配置
```yaml
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
desensitize:
enable: true//是否激活数据敏感,当为false时,不会对敏感内容编码
encoder: AES256Encoder//AES256编码器
mask_encoder://掩码类型编码相关配置,主要用于日志
len: 12
mode: 0
char: "#"
decoder: AES256Decoder//AES256解码器
secret:
properties: idType//敏感属性,多个可用','分隔
excludes: email//排除属性,即在Response中移除
resource://规则配置文件相关
dir: desensitized
post: "*.json"
logger:
properties: idType,idNumber//日志敏感属性,多个可用','分隔
encoder: MaskEncoder//指定日志编码器
excludes: customerId//日志中不显示属性
```
2. Json配置文件
```json
{
"rules": [
{
"encrypts": ["idNumber"],
"excludes": ["employeeId"]
}
]
}
```
##### 日志配置
日志配置有两种方式,只支持在Logger中直接输出对象,基础类型无法脱敏。
1、Properties指定messageFactory
> 在项目resources目录下加一个`log4j2.component.properties`配置文件
```properties
log4j2.messageFactory=com.yy.tech.data.logger.message.DesensitizedParameterizedMessageFactory
```
2. log4j2配置pattern
> 把默认的msg->smsg
```xml
[%d{yyyy-MM-dd HH:mm:ss.SSS}][%-5p][%T][%c.%M:%L] %smsg%xEx%n
```
##### 编码解码器
1. AES256 AES256Encoder/AES256Decoder
2. Base64 BASE64Encoder/BASE64Decoder
3. Mask掩码(主要应用于日志)MaskEncoder
扩展时,需要分别实现Encoder或是Decoder接口,如
编码:
```java
@Component(SecretContent.ENCODER_BASE64)
class Base64Encoder extends StdConverter implements Encoder {
@Autowired
private Base64Secret secret;
@Override
public String convert(final String str) {
return secret.encrypt(str);
}
}
@Component(SecretContent.ENCODER_AES256)
class Aes256Encoder extends StdConverter implements Encoder{
@Autowired
private Aes256Secret secret;
@Override
public String convert(final String s) {
return secret.encrypt(s);
}
}
```
解码
```java
@Component(SecretContent.DECODER_BASE64)
class Base64Decoder extends StdConverter implements Decoder {
@Autowired
private Base64Secret secret;
@Override
public String convert(final String str) {
return secret.decrypt(str);
}
}
@Component(SecretContent.DECODER_AES256)
class Aes256Decoder extends StdConverter implements Decoder {
@Autowired
private Aes256Secret secret;
@Override
public String convert(final String str) {
return secret.decrypt(str);
}
}
```
##### 如何自定义编码解码器
1. 在环境参数中指定,全局
2. 在`@SecretProperty`或是`@SecretParam`中指定,可具体到属性
3. 在规则配置文件中指定