From f77007c4b77c31b687cdf8864f6ff87209110f78 Mon Sep 17 00:00:00 2001 From: hongawen <83944980@qq.com> Date: Mon, 13 Jul 2026 16:23:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(file):=20=E5=AE=9E=E7=8E=B0=E6=96=87?= =?UTF-8?q?=E4=BB=B6=E5=88=A0=E9=99=A4=E6=9D=83=E9=99=90=E6=8E=A7=E5=88=B6?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 新增 FILE_DELETE_NO_PERMISSION 错误码用于无权删除文件的提示 - 移除控制器层的 @PreAuthorize 注解,将权限校验逻辑下沉到服务层 - 在 FileServiceImpl 中注入 SecurityFrameworkService 进行权限验证 - 实现 validateFileDeletePermission 方法校验删除权限 - 支持上传者本人可删除自己上传的文件,管理员仍保留全局删除权限 - 批量删除时逐个校验权限,任一越权即整体拒绝操作 --- .../system/enums/ErrorCodeConstants.java | 1 + .../controller/admin/file/FileController.java | 5 ++-- .../system/service/file/FileServiceImpl.java | 29 +++++++++++++++++++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ErrorCodeConstants.java b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ErrorCodeConstants.java index 34d70bd..fc2dbff 100644 --- a/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ErrorCodeConstants.java +++ b/rdms-system/rdms-system-api/src/main/java/com/njcn/rdms/module/system/enums/ErrorCodeConstants.java @@ -106,6 +106,7 @@ public interface ErrorCodeConstants { ErrorCode FILE_PATH_EXISTS = new ErrorCode(1_001_003_000, "文件路径已存在"); ErrorCode FILE_NOT_EXISTS = new ErrorCode(1_001_003_001, "文件不存在"); ErrorCode FILE_IS_EMPTY = new ErrorCode(1_001_003_002, "文件为空"); + ErrorCode FILE_DELETE_NO_PERMISSION = new ErrorCode(1_001_003_003, "无权删除该文件,仅可删除本人上传的文件"); // ========== OAuth2 客户端 1-002-020-000 ========= ErrorCode OAUTH2_CLIENT_NOT_EXISTS = new ErrorCode(1_002_020_000, "OAuth2 客户端不存在"); diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/file/FileController.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/file/FileController.java index 6176446..494d6a0 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/file/FileController.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/controller/admin/file/FileController.java @@ -84,7 +84,8 @@ public class FileController { @DeleteMapping("/delete") @Operation(summary = "删除文件") @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('system:file:delete')") + // 权限下沉到 FileService:上传者本人可删自己上传的文件,其余需 system:file:delete 权限。 + // 故意不挂 @PreAuthorize,否则无该权限码的上传者会在进方法体前被 AOP 挡死(口径同项目域"属主放行+权限码兜底")。 public CommonResult deleteFile(@RequestParam("id") Long id) throws Exception { fileService.deleteFile(id); return success(true); @@ -93,7 +94,7 @@ public class FileController { @DeleteMapping("/delete-list") @Operation(summary = "批量删除文件") @Parameter(name = "ids", description = "编号列表", required = true) - @PreAuthorize("@ss.hasPermission('system:file:delete')") + // 权限下沉到 FileService:逐个按上传者归属校验,其余需 system:file:delete 权限(见 deleteFile 注释)。 public CommonResult deleteFileList(@RequestParam("ids") List ids) throws Exception { fileService.deleteFileList(ids); return success(true); diff --git a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/file/FileServiceImpl.java b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/file/FileServiceImpl.java index 8432844..38eafcc 100644 --- a/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/file/FileServiceImpl.java +++ b/rdms-system/rdms-system-boot/src/main/java/com/njcn/rdms/module/system/service/file/FileServiceImpl.java @@ -10,6 +10,8 @@ import com.google.common.annotations.VisibleForTesting; import com.njcn.rdms.framework.common.pojo.PageResult; import com.njcn.rdms.framework.common.util.http.HttpUtils; import com.njcn.rdms.framework.common.util.object.BeanUtils; +import com.njcn.rdms.framework.security.core.service.SecurityFrameworkService; +import com.njcn.rdms.framework.security.core.util.SecurityFrameworkUtils; import com.njcn.rdms.module.system.controller.admin.file.vo.file.FileCreateReqVO; import com.njcn.rdms.module.system.controller.admin.file.vo.file.FilePageReqVO; import com.njcn.rdms.module.system.controller.admin.file.vo.file.FilePresignedUrlRespVO; @@ -27,6 +29,7 @@ import java.util.List; import static cn.hutool.core.date.DatePattern.PURE_DATE_PATTERN; import static com.njcn.rdms.framework.common.exception.util.ServiceExceptionUtil.exception; +import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.FILE_DELETE_NO_PERMISSION; import static com.njcn.rdms.module.system.enums.ErrorCodeConstants.FILE_NOT_EXISTS; /** @@ -52,6 +55,9 @@ public class FileServiceImpl implements FileService { @Resource private FileContentMapper fileContentMapper; + @Resource + private SecurityFrameworkService securityFrameworkService; + @Override public PageResult getFilePage(FilePageReqVO pageReqVO) { return fileMapper.selectPage(pageReqVO); @@ -172,6 +178,8 @@ public class FileServiceImpl implements FileService { public void deleteFile(Long id) throws Exception { // 校验存在 FileDO file = validateFileExists(id); + // 校验删除权限:上传者本人,或具备文件删除权限者 + validateFileDeletePermission(file); // 从文件存储器中删除 FileClient client = fileConfigService.getFileClient(file.getConfigId()); @@ -187,6 +195,8 @@ public class FileServiceImpl implements FileService { public void deleteFileList(List ids) { // 删除文件 List files = fileMapper.selectByIds(ids); + // 逐个校验删除权限,任一越权即整体拒绝 + files.forEach(this::validateFileDeletePermission); for (FileDO file : files) { // 获取客户端 FileClient client = fileConfigService.getFileClient(file.getConfigId()); @@ -207,6 +217,25 @@ public class FileServiceImpl implements FileService { return fileDO; } + /** + * 校验文件删除权限。 + *

+ * 口径:上传者本人可删除自己上传的文件;其余情况需具备文件管理删除权限 {@code system:file:delete}(运维 / 管理员)。 + * 该接口按 id 删除、不校验业务归属,故不能对所有登录用户放开,只对"本人上传"放行。 + */ + private void validateFileDeletePermission(FileDO file) { + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + // 上传者本人放行(creator 存的是上传时的登录用户 id) + if (loginUserId != null && String.valueOf(loginUserId).equals(file.getCreator())) { + return; + } + // 兜底:具备文件删除权限者(运维 / 管理员)可删除任意文件 + if (securityFrameworkService.hasPermission("system:file:delete")) { + return; + } + throw exception(FILE_DELETE_NO_PERMISSION); + } + @Override public byte[] getFileContent(Long configId, String path) throws Exception { // 软删 / 不存在的记录直接拒绝