init desensitize
parent
e8c9b1dea9
commit
a5acb554cd
|
@ -0,0 +1,91 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>2.6.2</version>
|
||||||
|
<relativePath/> <!-- lookup parent from repository -->
|
||||||
|
</parent>
|
||||||
|
<groupId>org.applesline</groupId>
|
||||||
|
<artifactId>desensitize</artifactId>
|
||||||
|
<version>1.0.0</version>
|
||||||
|
<name>desensitize</name>
|
||||||
|
<description>数据脱敏工具库</description>
|
||||||
|
<properties>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
</properties>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.aspectj</groupId>
|
||||||
|
<artifactId>aspectjweaver</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.jayway.jsonpath</groupId>
|
||||||
|
<artifactId>json-path</artifactId>
|
||||||
|
<version>2.2.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.code.gson</groupId>
|
||||||
|
<artifactId>gson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-deploy-plugin</artifactId>
|
||||||
|
<version>2.8.2</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>default-deploy</id>
|
||||||
|
<phase>deploy</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>deploy</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-source-plugin</artifactId>
|
||||||
|
<version>3.2.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>attach-sources</id>
|
||||||
|
<goals>
|
||||||
|
<goal>jar</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.sonatype.plugins</groupId>
|
||||||
|
<artifactId>nexus-staging-maven-plugin</artifactId>
|
||||||
|
<version>1.5.1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>default-deploy</id>
|
||||||
|
<phase>deploy</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>deploy</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.applesline.desensitize.annotation;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/13
|
||||||
|
*/
|
||||||
|
@Target({ElementType.METHOD})
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Documented
|
||||||
|
public @interface Desensitize {
|
||||||
|
|
||||||
|
FieldMapping[] fieldMapping() default {};
|
||||||
|
|
||||||
|
String[] ignoreByJpe() default {};
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.applesline.desensitize.annotation;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.config.AutoDesensitizeConfiguration;
|
||||||
|
import org.applesline.desensitize.config.AutoDesensitizeRegistrar;
|
||||||
|
import org.springframework.context.annotation.Import;
|
||||||
|
|
||||||
|
import java.lang.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/19
|
||||||
|
*/
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.TYPE)
|
||||||
|
@Documented
|
||||||
|
@Import({AutoDesensitizeConfiguration.class, AutoDesensitizeRegistrar.class})
|
||||||
|
public @interface EnableDesensitize {
|
||||||
|
|
||||||
|
FieldMapping[] fieldMapping() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ignore by JsonPath expression language
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
String[] ignoreByJpe() default {};
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package org.applesline.desensitize.annotation;
|
||||||
|
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/14
|
||||||
|
*/
|
||||||
|
public @interface FieldMapping {
|
||||||
|
|
||||||
|
DesensitizeType type();
|
||||||
|
|
||||||
|
String[] fields() default {};
|
||||||
|
}
|
|
@ -0,0 +1,69 @@
|
||||||
|
package org.applesline.desensitize.aop;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.annotation.Desensitize;
|
||||||
|
import org.applesline.desensitize.annotation.FieldMapping;
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
import org.applesline.desensitize.executor.DesensitizeExecutor;
|
||||||
|
import org.applesline.desensitize.executor.JsonPathDesensitizeExecutor;
|
||||||
|
import org.applesline.desensitize.handle.DesensitizeHandlerSelector;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.Signature;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/14
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
public class DesensitizeAdvice implements ApplicationContextAware {
|
||||||
|
|
||||||
|
private DesensitizeExecutor desensitizeExecutor;
|
||||||
|
private DesensitizeExecutor globalDesensitizeExecutor;
|
||||||
|
|
||||||
|
public DesensitizeAdvice(DesensitizeExecutor desensitizeExecutor) {
|
||||||
|
this.desensitizeExecutor = desensitizeExecutor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("@annotation(org.applesline.desensitize.annotation.Desensitize)")
|
||||||
|
public Object desensitize(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
|
||||||
|
Signature signature = proceedingJoinPoint.getSignature();
|
||||||
|
Object obj = proceedingJoinPoint.proceed();
|
||||||
|
if (signature instanceof MethodSignature) {
|
||||||
|
MethodSignature methodSignature = (MethodSignature)signature;
|
||||||
|
Desensitize desensitize = methodSignature.getMethod().getAnnotation(Desensitize.class);
|
||||||
|
Map<String, DesensitizeType> fieldMappingMap = new HashMap<>();
|
||||||
|
FieldMapping[] fieldMappings = desensitize.fieldMapping();
|
||||||
|
for (FieldMapping fieldMapping : fieldMappings) {
|
||||||
|
DesensitizeType desensitizeType = fieldMapping.type();
|
||||||
|
String[] fields = fieldMapping.fields();
|
||||||
|
for (String field : fields) {
|
||||||
|
fieldMappingMap.putIfAbsent(field,desensitizeType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (fieldMappingMap.isEmpty()) {
|
||||||
|
obj = globalDesensitizeExecutor.executeMask(obj);
|
||||||
|
} else {
|
||||||
|
desensitizeExecutor.configFields(fieldMappingMap, Arrays.stream(desensitize.ignoreByJpe()).collect(Collectors.toList()));
|
||||||
|
obj = desensitizeExecutor.executeMask(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
DesensitizeHandlerSelector selector = applicationContext.getBean(DesensitizeHandlerSelector.class);
|
||||||
|
this.globalDesensitizeExecutor = new JsonPathDesensitizeExecutor(selector);
|
||||||
|
this.globalDesensitizeExecutor.configFields(this.desensitizeExecutor.getMaskWordsMap(),this.desensitizeExecutor.getIgnoreJsonPathExpression());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package org.applesline.desensitize.config;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.aop.DesensitizeAdvice;
|
||||||
|
import org.applesline.desensitize.executor.DesensitizeExecutor;
|
||||||
|
import org.applesline.desensitize.executor.JsonPathDesensitizeExecutor;
|
||||||
|
import org.applesline.desensitize.handle.DesensitizeHandlerSelector;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/18
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class AutoDesensitizeConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DesensitizeHandlerSelector maskHandlerSelector() {
|
||||||
|
return new DesensitizeHandlerSelector();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DesensitizeExecutor maskSensitiveExecutor(DesensitizeHandlerSelector desensitizeHandlerSelector) {
|
||||||
|
return new JsonPathDesensitizeExecutor(desensitizeHandlerSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public DesensitizeAdvice desensitizeAdvice(DesensitizeExecutor desensitizeExecutor) {
|
||||||
|
return new DesensitizeAdvice(desensitizeExecutor);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
package org.applesline.desensitize.config;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.annotation.EnableDesensitize;
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
import org.applesline.desensitize.handle.impl.AddressHandler;
|
||||||
|
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||||
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
|
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
|
||||||
|
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||||
|
import org.springframework.core.annotation.AnnotationAttributes;
|
||||||
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/19
|
||||||
|
*/
|
||||||
|
public class AutoDesensitizeRegistrar implements ImportBeanDefinitionRegistrar {
|
||||||
|
|
||||||
|
private static final String DESENSITIZE_BEAN_POST_PROCESSOR = "desensitizeBeanPostProcessor";
|
||||||
|
private static final String FIELD_MAPPING = "fieldMapping";
|
||||||
|
private static final String IGNORE_BY_JSONPATH_EXPRESS = "ignoreByJpe";
|
||||||
|
private static final String TYPE = "type";
|
||||||
|
private static final String FIELDS = "fields";
|
||||||
|
|
||||||
|
private static final String SCAN_DESENSITIZE_HANDLER_BASE_PACKAGE = AddressHandler.class.getPackage().getName();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
|
||||||
|
Map<String, Object> defaultAttrs = importingClassMetadata.getAnnotationAttributes(EnableDesensitize.class.getName());
|
||||||
|
|
||||||
|
AnnotationAttributes[] annotationAttributes = (AnnotationAttributes[]) defaultAttrs.get(FIELD_MAPPING);
|
||||||
|
Map<String, DesensitizeType> fieldMappingMap = new HashMap<>();
|
||||||
|
for (AnnotationAttributes annotationAttribute : annotationAttributes) {
|
||||||
|
String[] fields = (String[])annotationAttribute.get(FIELDS);
|
||||||
|
DesensitizeType desensitizeType = (DesensitizeType)annotationAttribute.get(TYPE);
|
||||||
|
for (String field : fields) {
|
||||||
|
fieldMappingMap.putIfAbsent(field,desensitizeType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String[] ignoreByJsonPathExpress = (String[])defaultAttrs.get(IGNORE_BY_JSONPATH_EXPRESS);
|
||||||
|
List<String> jpeList = new ArrayList<>();
|
||||||
|
for (String str : ignoreByJsonPathExpress) {
|
||||||
|
if (!StringUtils.isEmpty(str.trim())) {
|
||||||
|
jpeList.add(str.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!registry.containsBeanDefinition(DESENSITIZE_BEAN_POST_PROCESSOR)) {
|
||||||
|
AbstractBeanDefinition beanDefinition = BeanDefinitionBuilder
|
||||||
|
.genericBeanDefinition(DesensitizeBeanPostProcessor.class)
|
||||||
|
.addConstructorArgValue(fieldMappingMap)
|
||||||
|
.addConstructorArgValue(jpeList)
|
||||||
|
.getBeanDefinition();
|
||||||
|
registry.registerBeanDefinition(DESENSITIZE_BEAN_POST_PROCESSOR, beanDefinition);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassPathBeanDefinitionScanner scanner = new ClassPathBeanDefinitionScanner(registry);
|
||||||
|
scanner.scan(SCAN_DESENSITIZE_HANDLER_BASE_PACKAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
package org.applesline.desensitize.config;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
import org.applesline.desensitize.executor.JsonPathDesensitizeExecutor;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/20
|
||||||
|
*/
|
||||||
|
public class DesensitizeBeanPostProcessor implements BeanPostProcessor {
|
||||||
|
|
||||||
|
Map<String, DesensitizeType> maskFieldMapping;
|
||||||
|
List<String> ignoreByJsonPathExpress;
|
||||||
|
|
||||||
|
public DesensitizeBeanPostProcessor(Map<String, DesensitizeType> maskFieldMapping, List<String> ignoreByJsonPathExpress) {
|
||||||
|
this.maskFieldMapping = maskFieldMapping;
|
||||||
|
this.ignoreByJsonPathExpress = ignoreByJsonPathExpress;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||||
|
if (bean.getClass() == JsonPathDesensitizeExecutor.class) {
|
||||||
|
JsonPathDesensitizeExecutor executor = (JsonPathDesensitizeExecutor)bean;
|
||||||
|
executor.configFields(maskFieldMapping,ignoreByJsonPathExpress);
|
||||||
|
}
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package org.applesline.desensitize.constants;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/14
|
||||||
|
*/
|
||||||
|
public enum DesensitizeType {
|
||||||
|
|
||||||
|
EMAIL,
|
||||||
|
MOBILE,
|
||||||
|
PASSWORD,
|
||||||
|
USER_ID,
|
||||||
|
IP,
|
||||||
|
ADDRESS,
|
||||||
|
OTHER_CARD,
|
||||||
|
BANK_CARD,
|
||||||
|
CAR_LICENSE,
|
||||||
|
GENDER,
|
||||||
|
BIRTHDAY,
|
||||||
|
CHINESE_NAME,
|
||||||
|
ID_CARD;
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.applesline.desensitize.executor;
|
||||||
|
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/13
|
||||||
|
*/
|
||||||
|
public interface DesensitizeExecutor {
|
||||||
|
|
||||||
|
void configFields(Map<String, DesensitizeType> maskWordsMap, Collection<String> ignoreJsonPathExpression);
|
||||||
|
|
||||||
|
Map<String, DesensitizeType> getMaskWordsMap();
|
||||||
|
|
||||||
|
Collection<String> getIgnoreJsonPathExpression();
|
||||||
|
|
||||||
|
Object executeMask(Object obj);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
package org.applesline.desensitize.executor;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
import org.applesline.desensitize.handle.DesensitizeHandlerSelector;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/17
|
||||||
|
*/
|
||||||
|
public class DesensitizeExecutorAdapter implements DesensitizeExecutor {
|
||||||
|
|
||||||
|
protected DesensitizeHandlerSelector desensitizeHandlerSelector;
|
||||||
|
|
||||||
|
protected Map<String, DesensitizeType> maskWordsMap;
|
||||||
|
protected Collection<String> ignoreJsonPathExpression;
|
||||||
|
|
||||||
|
public DesensitizeExecutorAdapter(DesensitizeHandlerSelector desensitizeHandlerSelector) {
|
||||||
|
this.desensitizeHandlerSelector = desensitizeHandlerSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Gson gson = new GsonBuilder().create();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configFields(Map<String, DesensitizeType> maskWordsMap, Collection<String> ignoreJsonPathExpression) {
|
||||||
|
this.maskWordsMap = maskWordsMap;
|
||||||
|
this.ignoreJsonPathExpression = ignoreJsonPathExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, DesensitizeType> getMaskWordsMap() {
|
||||||
|
return this.maskWordsMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<String> getIgnoreJsonPathExpression() {
|
||||||
|
return this.ignoreJsonPathExpression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object executeMask(Object obj) {
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long doMask(DesensitizeType desensitizeType) {
|
||||||
|
return desensitizeHandlerSelector.getService(desensitizeType).doMask();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String doMask(DesensitizeType desensitizeType, String origin) {
|
||||||
|
return desensitizeHandlerSelector.getService(desensitizeType).doMask(origin);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.applesline.desensitize.executor;
|
||||||
|
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
import com.jayway.jsonpath.JsonPath;
|
||||||
|
import org.applesline.desensitize.handle.DesensitizeHandlerSelector;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/14
|
||||||
|
*/
|
||||||
|
public class JsonPathDesensitizeExecutor extends DesensitizeExecutorAdapter {
|
||||||
|
|
||||||
|
public JsonPathDesensitizeExecutor(DesensitizeHandlerSelector desensitizeHandlerSelector) {
|
||||||
|
super(desensitizeHandlerSelector);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object executeMask(Object obj) {
|
||||||
|
JsonElement jsonTree = gson.toJsonTree(obj);
|
||||||
|
maskSensitiveWords(jsonTree,matchIgnoreFields(obj));
|
||||||
|
return gson.fromJson(jsonTree.toString(),obj.getClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void maskSensitiveWords(JsonElement originElement,Collection<String> ignoreMaskWords) {
|
||||||
|
Set<String> needMaskWords = maskWordsMap.keySet();
|
||||||
|
if (originElement.isJsonArray()) {
|
||||||
|
JsonArray jsonArray = originElement.getAsJsonArray();
|
||||||
|
for (JsonElement jsonElement : jsonArray) {
|
||||||
|
maskSensitiveWords(jsonElement,ignoreMaskWords);
|
||||||
|
}
|
||||||
|
} else if (originElement.isJsonObject()) {
|
||||||
|
JsonObject jsonObject = originElement.getAsJsonObject();
|
||||||
|
for (Map.Entry<String,JsonElement> entry : originElement.getAsJsonObject().entrySet()) {
|
||||||
|
JsonElement element = entry.getValue();
|
||||||
|
if (element.isJsonArray()) {
|
||||||
|
maskSensitiveWords(element.getAsJsonArray(),ignoreMaskWords);
|
||||||
|
} else if (element.isJsonObject()) {
|
||||||
|
maskSensitiveWords(element.getAsJsonObject(),ignoreMaskWords);
|
||||||
|
} else {
|
||||||
|
if (needMaskWords.contains(entry.getKey()) && !ignoreMaskWords.contains(entry.getValue().getAsString())) {
|
||||||
|
if (element.getAsJsonPrimitive().isNumber()) {
|
||||||
|
jsonObject.addProperty(entry.getKey(), doMask(maskWordsMap.get(entry.getKey())));
|
||||||
|
} else {
|
||||||
|
jsonObject.addProperty(entry.getKey(), doMask(maskWordsMap.get(entry.getKey()),entry.getValue().getAsString()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Collection<String> matchIgnoreFields(Object obj) {
|
||||||
|
Collection<String> ignoreMaskFields = new HashSet<>();
|
||||||
|
for (String ignoreJpe : ignoreJsonPathExpression) {
|
||||||
|
Object field = JsonPath.read(gson.toJsonTree(obj).toString(),ignoreJpe);
|
||||||
|
if (field instanceof Collection) {
|
||||||
|
ignoreMaskFields.addAll((Collection<? extends String>) field);
|
||||||
|
} else {
|
||||||
|
ignoreMaskFields.add(String.valueOf(field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ignoreMaskFields;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,131 @@
|
||||||
|
package org.applesline.desensitize.handle;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 屏蔽敏感字段处理器。
|
||||||
|
*
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/14
|
||||||
|
*/
|
||||||
|
public class DesensitizeAdapter implements DesensitizeHandler {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String doMask(String fieldValue) {
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long doMask() {
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String maskCardNumber(String idCardNum,int front,int end) {
|
||||||
|
if (!isBlank(idCardNum) && front + end > idCardNum.length()) {
|
||||||
|
return front >= 0 && end >= 0 ? hide(idCardNum, front, idCardNum.length() - end) : "";
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String hide(CharSequence str, int startInclude, int endExclude) {
|
||||||
|
return replace(str, startInclude, endExclude, '*');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String replace(CharSequence str, int startInclude, int endExclude, char replacedChar) {
|
||||||
|
if (isEmpty(str)) {
|
||||||
|
return str(str);
|
||||||
|
} else {
|
||||||
|
int strLength = str.length();
|
||||||
|
if (startInclude > strLength) {
|
||||||
|
return str(str);
|
||||||
|
} else {
|
||||||
|
if (endExclude > strLength) {
|
||||||
|
endExclude = strLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startInclude > endExclude) {
|
||||||
|
return str(str);
|
||||||
|
} else {
|
||||||
|
char[] chars = new char[strLength];
|
||||||
|
|
||||||
|
for(int i = 0; i < strLength; ++i) {
|
||||||
|
if (i >= startInclude && i < endExclude) {
|
||||||
|
chars[i] = replacedChar;
|
||||||
|
} else {
|
||||||
|
chars[i] = str.charAt(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String(chars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int indexOf(CharSequence seq, int searchChar) {
|
||||||
|
return isEmpty(seq) ? -1 : indexOf(seq, searchChar, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private int indexOf(final CharSequence cs, final int searchChar, int start) {
|
||||||
|
if (cs instanceof String) {
|
||||||
|
return ((String)cs).indexOf(searchChar, start);
|
||||||
|
} else {
|
||||||
|
int sz = cs.length();
|
||||||
|
if (start < 0) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = start; i < sz; ++i) {
|
||||||
|
if (cs.charAt(i) == searchChar) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isEmpty(CharSequence cs) {
|
||||||
|
return cs == null || cs.length() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String str(CharSequence cs) {
|
||||||
|
return cs == null ? null : cs.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String repeat(char c, int count) {
|
||||||
|
if (count <= 0) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
char[] result = new char[count];
|
||||||
|
|
||||||
|
for(int i = 0; i < count; ++i) {
|
||||||
|
result[i] = c;
|
||||||
|
}
|
||||||
|
return new String(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected boolean isBlank(CharSequence cs) {
|
||||||
|
int strLen;
|
||||||
|
if (cs != null && (strLen = cs.length()) != 0) {
|
||||||
|
for(int i = 0; i < strLen; ++i) {
|
||||||
|
if (!Character.isWhitespace(cs.charAt(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String trim(String str) {
|
||||||
|
return str == null ? null : str.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DesensitizeType getFieldType() {
|
||||||
|
throw new RuntimeException();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.applesline.desensitize.handle;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 屏蔽敏感字段处理器。
|
||||||
|
*
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/14
|
||||||
|
*/
|
||||||
|
public interface DesensitizeHandler {
|
||||||
|
|
||||||
|
String doMask(String fieldValue);
|
||||||
|
|
||||||
|
Long doMask();
|
||||||
|
|
||||||
|
DesensitizeType getFieldType();
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package org.applesline.desensitize.handle;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
import org.springframework.beans.BeansException;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/14
|
||||||
|
*/
|
||||||
|
public class DesensitizeHandlerSelector implements ApplicationContextAware {
|
||||||
|
|
||||||
|
private Map<DesensitizeType, DesensitizeHandler> serviceMap = new HashMap<>();
|
||||||
|
|
||||||
|
public DesensitizeHandler getService(DesensitizeType desensitizeType) {
|
||||||
|
return serviceMap.get(desensitizeType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||||
|
Map<String,DesensitizeHandler> handlers = applicationContext.getBeansOfType(DesensitizeHandler.class);
|
||||||
|
handlers.values().forEach(handler->{
|
||||||
|
serviceMap.putIfAbsent(handler.getFieldType(),handler);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package org.applesline.desensitize.handle.impl;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
import org.applesline.desensitize.handle.DesensitizeAdapter;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/13
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class AddressHandler extends DesensitizeAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String doMask(String address) {
|
||||||
|
if (isBlank(address)) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
int length = address.length();
|
||||||
|
return hide(address, length - 8, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DesensitizeType getFieldType() {
|
||||||
|
return DesensitizeType.ADDRESS;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
package org.applesline.desensitize.handle.impl;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
import org.applesline.desensitize.handle.DesensitizeAdapter;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/13
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BankCardHandler extends DesensitizeAdapter {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String doMask(String bankCardNo) {
|
||||||
|
if (isBlank(bankCardNo)) {
|
||||||
|
return bankCardNo;
|
||||||
|
} else {
|
||||||
|
bankCardNo = trim(bankCardNo);
|
||||||
|
if (bankCardNo.length() < 9) {
|
||||||
|
return bankCardNo;
|
||||||
|
} else {
|
||||||
|
int length = bankCardNo.length();
|
||||||
|
int midLength = length - 8;
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
buf.append(bankCardNo, 0, 4);
|
||||||
|
|
||||||
|
for(int i = 0; i < midLength; ++i) {
|
||||||
|
if (i % 4 == 0) {
|
||||||
|
buf.append(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.append('*');
|
||||||
|
}
|
||||||
|
|
||||||
|
buf.append(" ").append(bankCardNo, length - 4, length);
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DesensitizeType getFieldType() {
|
||||||
|
return DesensitizeType.BANK_CARD;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
package org.applesline.desensitize.handle.impl;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
import org.applesline.desensitize.handle.DesensitizeAdapter;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/19
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class BirthdayHandler extends DesensitizeAdapter {
|
||||||
|
@Override
|
||||||
|
public String doMask(String birthday) {
|
||||||
|
return isBlank(birthday) ? "" : "****-**-**";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DesensitizeType getFieldType() {
|
||||||
|
return DesensitizeType.BIRTHDAY;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
package org.applesline.desensitize.handle.impl;
|
||||||
|
|
||||||
|
import org.applesline.desensitize.constants.DesensitizeType;
|
||||||
|
import org.applesline.desensitize.handle.DesensitizeAdapter;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author liuyaping
|
||||||
|
* @date 2022/1/19
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class CarLicenseHandler extends DesensitizeAdapter {
|
||||||
|
@Override
|
||||||
|
public String doMask(String carLicense) {
|
||||||
|
if (isBlank(carLicense)) {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
if (carLicense.length() == 7) {
|
||||||
|
carLicense = hide(carLicense, 3, 6);
|
||||||
|
} else if (carLicense.length() == 8) {
|
||||||
|
carLicense = hide(carLicense, 3, 7);
|
||||||
|
}
|
||||||
|
|
||||||
|
return carLicense;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DesensitizeType getFieldType() {
|
||||||
|
return DesensitizeType.CAR_LICENSE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
|
Loading…
Reference in New Issue