Skip to content

Commit

Permalink
feat-IDesensitizationAbility-实现数据脱敏相关算法
Browse files Browse the repository at this point in the history
  • Loading branch information
aruis committed Sep 15, 2024
1 parent d870f67 commit cbe9537
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 1 deletion.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
- [x] 数据查询-多表关联
- [x] 数据查询-主子表关联
- [x] 数据查询-树形构建
- [ ] 数据脱敏
- [x] 数据脱敏
* [ ] 扩展能力接入
- [x] 代码内创建表
- [x] 软删除
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package net.ximatai.muyun.test.core;

import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import jakarta.inject.Inject;
import jakarta.ws.rs.Path;
import net.ximatai.muyun.ability.IDesensitizationAbility;
import net.ximatai.muyun.ability.ITableCreateAbility;
import net.ximatai.muyun.ability.curd.std.ICURDAbility;
import net.ximatai.muyun.core.Scaffold;
import net.ximatai.muyun.core.desensitization.Desensitizer;
import net.ximatai.muyun.core.desensitization.MaskMiddleAlgorithm;
import net.ximatai.muyun.core.security.SMEncryptor;
import net.ximatai.muyun.database.IDatabaseAccess;
import net.ximatai.muyun.database.builder.Column;
import net.ximatai.muyun.database.builder.TableWrapper;
import net.ximatai.muyun.test.testcontainers.PostgresTestResource;
import org.junit.jupiter.api.Test;

import java.util.Map;

import static org.junit.jupiter.api.Assertions.*;

@QuarkusTest
@QuarkusTestResource(value = PostgresTestResource.class, restrictToAnnotatedClass = true)
class TestDesensitizationAbility {

private String path = "/TestSecurityAbility";

@Inject
SMEncryptor smEncryptor;

@Inject
IDatabaseAccess databaseAccess;

@Inject
TestDesensitizationAbilityController testController;

@Test
void test() {
String text = "hello world!";
String id = testController.create(Map.of(
"v_name", text
));
Map<String, ?> response = testController.view(id);

String responseVName = (String) response.get("v_name");
assertEquals(text.length(), responseVName.length());
assertNotEquals(text, responseVName);
assertEquals("h**********!", responseVName);
assertNull(response.get("v_name2"));
}

}

@Path("/TestDesensitizationAbility")
class TestDesensitizationAbilityController extends Scaffold implements ICURDAbility, ITableCreateAbility, IDesensitizationAbility {

@Inject
SMEncryptor smEncryptor;

@Override
public String getSchemaName() {
return "test";
}

@Override
public String getMainTable() {
return "testdesensitizationability";
}

@Override
public TableWrapper fitOutTable() {
return TableWrapper.withName(getMainTable())
.setSchema(getSchemaName())
.setPrimaryKey(Column.ID_POSTGRES)
.addColumn(Column.of("v_name").setType("varchar"))
.addColumn(Column.of("v_name2").setType("varchar"))
.addColumn(Column.of("t_create").setDefaultValue("now()"));
}


@Override
public Desensitizer getDesensitizer() {
return new Desensitizer().registerAlgorithm("v_name", new MaskMiddleAlgorithm());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package net.ximatai.muyun.ability;

import net.ximatai.muyun.core.desensitization.Desensitizer;

import java.util.Map;

public interface IDesensitizationAbility {

Desensitizer getDesensitizer();

default void desensitize(Map<String, Object> map) {
Desensitizer desensitizer = getDesensitizer();
if (desensitizer == null) return;

map.replaceAll((k, v) -> v != null ? desensitizer.desensitize(k, v.toString()) : null);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import jakarta.ws.rs.PathParam;
import jakarta.ws.rs.QueryParam;
import net.ximatai.muyun.ability.IDatabaseAbilityStd;
import net.ximatai.muyun.ability.IDesensitizationAbility;
import net.ximatai.muyun.ability.IMetadataAbility;
import net.ximatai.muyun.ability.IReferenceAbility;
import net.ximatai.muyun.ability.ISecurityAbility;
Expand Down Expand Up @@ -89,6 +90,9 @@ default String getSelectSql() {
securityAbility.decrypt(row);
securityAbility.checkSign(row);
}
if (this instanceof IDesensitizationAbility desensitizationAbility) {
desensitizationAbility.desensitize(row);
}
return row;
}

Expand Down Expand Up @@ -247,6 +251,10 @@ default PageResult view(Integer page,
list.forEach(securityAbility::checkSign);
}

if (this instanceof IDesensitizationAbility desensitizationAbility) {
list.forEach(desensitizationAbility::desensitize);
}

return new PageResult<>(list, total, size, page);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package net.ximatai.muyun.core.desensitization;

import java.util.HashMap;
import java.util.Map;

public class Desensitizer {
private final Map<String, IDesensitizationAlgorithm> columnAlgorithmMap = new HashMap<>();

/**
* 注册列名及对应的脱敏算法
*
* @param columnName 列名
* @param algorithm 脱敏算法
*/
public Desensitizer registerAlgorithm(String columnName, IDesensitizationAlgorithm algorithm) {
columnAlgorithmMap.put(columnName, algorithm);
return this;
}

/**
* 根据列名获取对应的脱敏算法
*
* @param columnName 列名
* @return 对应的脱敏算法
*/
public IDesensitizationAlgorithm getAlgorithm(String columnName) {
return columnAlgorithmMap.get(columnName);
}

/**
* 根据列名和原始值进行脱敏
*
* @param columnName 列名
* @param source 原始数据
* @return 脱敏后的数据
*/
public String desensitize(String columnName, String source) {
IDesensitizationAlgorithm algorithm = getAlgorithm(columnName);
if (algorithm != null) {
return algorithm.desensitize(source);
}
return source; // 没有注册脱敏算法则返回原始数据
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package net.ximatai.muyun.core.desensitization;

public interface IDesensitizationAlgorithm {

String desensitize(String source);

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package net.ximatai.muyun.core.desensitization;

public class MaskMiddleAlgorithm implements IDesensitizationAlgorithm {
@Override
public String desensitize(String source) {
if (source == null || source.length() <= 2) {
return source; // 短字符串不进行脱敏
}
// 只显示首尾字符,中间使用 * 号代替
int length = source.length();
return source.charAt(0) + "*".repeat(length - 2) + source.charAt(length - 1);
}
}

0 comments on commit cbe9537

Please sign in to comment.