Skip to content

Commit

Permalink
feat-ISecurityAbility-初步实现数据加密、签名相关的能力
Browse files Browse the repository at this point in the history
  • Loading branch information
aruis committed Sep 13, 2024
1 parent de10928 commit 2b7b274
Show file tree
Hide file tree
Showing 8 changed files with 155 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package net.ximatai.muyun.ability;

import net.ximatai.muyun.core.security.AEncryptor;
import net.ximatai.muyun.database.builder.Column;

import java.util.List;
import java.util.Map;

public interface ISecurityAbility {

String SIGN_SUFFIX = "_sign_";

List<String> getColumnsForSigning();

List<String> getColumnsForEncryption();

AEncryptor getAEncryptor();

default String column2SignColumn(String column) {
return column + SIGN_SUFFIX;
}

/**
* 获取因为存在签名字段所以需要追加的列
*
* @return 额外的签名校验列
*/
default List<Column> getSignColumns() {
if (getColumnsForSigning() == null) return List.of();

return getColumnsForSigning().stream()
.map(this::column2SignColumn)
.map(Column::of)
.map(c -> c.setType("varchar"))
.toList();
}

/**
* 该签名签名、该加密加密
*
* @param map
*/
default void signAndEncrypt(Map map) {
AEncryptor encryptor = getAEncryptor();
if (encryptor == null) return;

getColumnsForSigning().forEach(s -> {
if (map.containsKey(s)) {
map.put(column2SignColumn(s), encryptor.sign(map.get(s).toString()));
}
});

getColumnsForEncryption().forEach(s -> {
if (map.containsKey(s)) {
map.put(s, encryptor.encrypt(map.get(s).toString()));
}
});
}

default void decrypt(Map map) {
AEncryptor encryptor = getAEncryptor();
if (encryptor == null) return;

getColumnsForEncryption().forEach(s -> {
if (map.containsKey(s)) {
map.put(s, encryptor.decrypt(map.get(s).toString()));
}
});
}

default void checkSign(Map map) {
AEncryptor encryptor = getAEncryptor();
if (encryptor == null) return;

getColumnsForSigning().forEach(s -> {
if (map.containsKey(s)) {
encryptor.checkSign(map.get(s).toString(), map.get(column2SignColumn(s)).toString());
}
});
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ default void create(IDatabaseAccess databaseAccess) {
if (this instanceof ISortAbility sortAbility) {
wrapper.addColumn(sortAbility.getSortColumn().getColumn());
}
if (this instanceof ISecurityAbility securityAbility) {
securityAbility.getSignColumns().forEach(wrapper::addColumn);
}
new TableBuilder(databaseAccess).build(wrapper);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
import jakarta.ws.rs.Path;
import net.ximatai.muyun.ability.IDatabaseAbilityStd;
import net.ximatai.muyun.ability.IMetadataAbility;
import net.ximatai.muyun.ability.ISecurityAbility;
import net.ximatai.muyun.ability.ISoftDeleteAbility;

import java.time.LocalDateTime;
import java.util.HashMap;
Expand All @@ -14,8 +16,11 @@ public interface ICreateAbility extends IDatabaseAbilityStd, IMetadataAbility {
@POST
@Path("/create")
default String create(Map body) {
HashMap map = new HashMap(body);
HashMap map = new HashMap<>(body);
fitOutDefaultValue(map);
if (this instanceof ISecurityAbility securityAbility) {
securityAbility.signAndEncrypt(map);
}
return getDatabase().insertItem(getSchemaName(), getMainTable(), map);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import net.ximatai.muyun.ability.IDatabaseAbilityStd;
import net.ximatai.muyun.ability.IMetadataAbility;
import net.ximatai.muyun.ability.IReferenceAbility;
import net.ximatai.muyun.ability.ISecurityAbility;
import net.ximatai.muyun.ability.ISoftDeleteAbility;
import net.ximatai.muyun.ability.ISortAbility;
import net.ximatai.muyun.core.exception.QueryException;
Expand Down Expand Up @@ -83,7 +84,12 @@ default String getSelectSql() {
@GET
@Path("/view/{id}")
default Map<String, ?> view(@PathParam("id") String id) {
return getDatabase().row(getSelectOneRowSql(), Map.of("id", id));
Map<String, Object> row = getDatabase().row(getSelectOneRowSql(), Map.of("id", id));
if (this instanceof ISecurityAbility securityAbility) {
securityAbility.decrypt(row);
securityAbility.checkSign(row);
}
return row;
}

@GET
Expand Down Expand Up @@ -228,14 +234,18 @@ default PageResult view(Integer page,
if (noPage != null && noPage) {
size = total;
page = 0;
} else {
// 添加分页参数
} else {// 添加分页参数
querySql.append(" offset ? limit ? ");
params.add((page - 1) * size);
params.add(size);
}

List<?> list = getDatabase().query(querySql.toString(), params);
List<Map<String, Object>> list = getDatabase().query(querySql.toString(), params);

if (this instanceof ISecurityAbility securityAbility) {
list.forEach(securityAbility::decrypt);
list.forEach(securityAbility::checkSign);
}

return new PageResult<>(list, total, size, page);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import jakarta.ws.rs.PathParam;
import net.ximatai.muyun.ability.IDatabaseAbilityStd;
import net.ximatai.muyun.ability.IMetadataAbility;
import net.ximatai.muyun.ability.ISecurityAbility;

import java.time.LocalDateTime;
import java.util.HashMap;
Expand All @@ -20,6 +21,9 @@ default Integer update(@PathParam("id") String id, Map body) {
HashMap map = new HashMap(body);
map.put(getPK(), id);
map.put("t_update", LocalDateTime.now());
if (this instanceof ISecurityAbility securityAbility) {
securityAbility.signAndEncrypt(map);
}

return getDatabase().updateItem(getSchemaName(), getMainTable(), map);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package net.ximatai.muyun.core.exception;

public class InvalidSignatureException extends RuntimeException {

public InvalidSignatureException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package net.ximatai.muyun.core.security;

import net.ximatai.muyun.core.exception.InvalidSignatureException;
import net.ximatai.muyun.util.StringUtil;

public abstract class AEncryptor {


public void checkSign(String source, String sign) {
if (StringUtil.isBlank(sign)) return;
if (StringUtil.isBlank(source)) return;
if (!sign.equals(sign(source))) {
throw new InvalidSignatureException("数据「%s」已被篡改".formatted(source));
}
}

abstract public String sign(String source);

abstract public String encrypt(String source);

abstract public String decrypt(String encodeText);
}
16 changes: 16 additions & 0 deletions my-core/src/main/java/net/ximatai/muyun/util/StringUtil.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package net.ximatai.muyun.util;

public class StringUtil {

public static boolean isBlank(Object x) {
return switch (x) {
case null -> true;
case String str -> str.isBlank() || "NULL".equalsIgnoreCase(str.trim());
default -> false;
};
}

public static boolean isNotBlank(Object x) {
return !isBlank(x);
}
}

0 comments on commit 2b7b274

Please sign in to comment.