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