fix: 存储管理及菜单管理功能优化 (#52)

存储管理功能优化:
1、私钥脱敏修改为注解/数据库敏感字段加密
2、兼容私钥脱敏修改场景下的数据回带
3、修复存储配置禁用情况下修改报错 || -> &&

菜单管理优化:
1、非外链类型菜单兼容"/"路径
This commit is contained in:
kils
2024-04-24 16:52:21 +08:00
committed by GitHub
parent 79a3de8971
commit f17076e128
4 changed files with 36 additions and 29 deletions

View File

@@ -21,6 +21,7 @@ import lombok.Data;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.system.enums.StorageTypeEnum;
import top.continew.starter.extension.crud.model.entity.BaseDO;
import top.continew.starter.security.crypto.annotation.FieldEncrypt;
import java.io.Serial;
@@ -55,11 +56,13 @@ public class StorageDO extends BaseDO {
/**
* Access Key访问密钥
*/
@FieldEncrypt
private String accessKey;
/**
* Secret Key私有密钥
*/
@FieldEncrypt
private String secretKey;
/**

View File

@@ -21,6 +21,7 @@ import lombok.Data;
import top.continew.admin.common.enums.DisEnableStatusEnum;
import top.continew.admin.system.enums.StorageTypeEnum;
import top.continew.starter.extension.crud.model.resp.BaseDetailResp;
import top.continew.starter.security.mask.annotation.JsonMask;
import java.io.Serial;
@@ -71,14 +72,9 @@ public class StorageResp extends BaseDetailResp {
* 私有密钥
*/
@Schema(description = "私有密钥", example = "")
@JsonMask(left = 4, right = 3)
private String secretKey;
/**
* 私有密钥加密串
*/
@Schema(description = "私有密钥加密串", example = "")
private String secretKeyEncrypted;
/**
* 终端节点
*/
@@ -119,4 +115,5 @@ public class StorageResp extends BaseDetailResp {
public Boolean getDisabled() {
return this.getIsDefault();
}
}

View File

@@ -22,6 +22,7 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.x.file.storage.core.FileStorageProperties;
import org.dromara.x.file.storage.core.FileStorageService;
import org.dromara.x.file.storage.core.FileStorageServiceBuilder;
@@ -57,51 +58,33 @@ import java.util.concurrent.CopyOnWriteArrayList;
*/
@Service
@RequiredArgsConstructor
@Slf4j
public class StorageServiceImpl extends BaseServiceImpl<StorageMapper, StorageDO, StorageResp, StorageResp, StorageQuery, StorageReq> implements StorageService {
private final FileStorageService fileStorageService;
@Resource
private FileService fileService;
@Override
protected void fill(Object obj) {
super.fill(obj);
if (obj instanceof StorageResp resp && StrUtil.isNotBlank(resp.getSecretKey())) {
resp.setSecretKeyEncrypted(SecureUtils.encryptByRsaPublicKey(resp.getSecretKey()));
resp.setSecretKey(StrUtil.hide(resp.getSecretKey(), 4, resp.getSecretKey().length() - 3));
}
}
@Override
protected void beforeAdd(StorageReq req) {
decryptSecretKey(req);
decodeSecretKey(req, null);
CheckUtils.throwIf(Boolean.TRUE.equals(req.getIsDefault()) && this.isDefaultExists(null), "请先取消原有默认存储");
String code = req.getCode();
CheckUtils.throwIf(this.isCodeExists(code, null), "新增失败,[{}] 已存在", code);
this.load(req);
}
private void decryptSecretKey(StorageReq req) {
if (!StorageTypeEnum.S3.equals(req.getType())) {
return;
}
String secretKey = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getSecretKey()));
ValidationUtils.throwIfNull(secretKey, "密钥解密失败");
req.setSecretKey(secretKey);
}
@Override
protected void beforeUpdate(StorageReq req, Long id) {
decryptSecretKey(req);
String code = req.getCode();
CheckUtils.throwIf(this.isCodeExists(code, id), "修改失败,[{}] 已存在", code);
DisEnableStatusEnum newStatus = req.getStatus();
StorageDO oldStorage = super.getById(id);
CheckUtils.throwIf(Boolean.TRUE.equals(oldStorage.getIsDefault()) && DisEnableStatusEnum.DISABLE
.equals(newStatus), "[{}] 是默认存储,不允许禁用", oldStorage.getName());
decodeSecretKey(req, oldStorage);
DisEnableStatusEnum oldStatus = oldStorage.getStatus();
if (DisEnableStatusEnum.ENABLE.equals(oldStatus) || DisEnableStatusEnum.DISABLE.equals(newStatus)) {
if (DisEnableStatusEnum.ENABLE.equals(oldStatus) && DisEnableStatusEnum.DISABLE.equals(newStatus)) {
this.unload(BeanUtil.copyProperties(oldStorage, StorageReq.class));
}
if (DisEnableStatusEnum.ENABLE.equals(newStatus)) {
@@ -113,6 +96,23 @@ public class StorageServiceImpl extends BaseServiceImpl<StorageMapper, StorageDO
}
}
private void decodeSecretKey(StorageReq req, StorageDO storage) {
if (!StorageTypeEnum.S3.equals(req.getType())) {
return;
}
// 修改Storage时如果SecretKey不修改字段脱敏无法回带手动设置
if ((StrUtil.isBlank(req.getSecretKey()) || req.getSecretKey().contains("*")) && StrUtil.isNotBlank(storage
.getSecretKey())) {
req.setSecretKey(storage.getSecretKey());
return;
}
String secretKey = ExceptionUtils.exToNull(() -> SecureUtils.decryptByRsaPrivateKey(req.getSecretKey()));
ValidationUtils.throwIfNull(secretKey, "私有密钥解密失败");
req.setSecretKey(secretKey);
}
@Override
protected void beforeDelete(List<Long> ids) {
CheckUtils.throwIf(fileService.countByStorageIds(ids) > 0, "所选存储存在文件关联,请删除文件后重试");