私人文件权限控制修改文档

📋 修改概述

修改目标：实现私人文件（isPublic=0）的严格访问控制，确保只有文件所有者本人可以查看和访问。
修改时间：2026-05-06 修改文件：FileServiceImpl.java 

影响范围：文件查询、文件详情查看、文件内容下载/预览功能

🔍 问题分析
原有问题
在修改前，系统的文件权限控制存在以下安全漏洞：
私人文件未隔离：即使是 isPublic=0 的私人文件，同部门的其他用户也能看到和访问
权限检查缺失：checkFilePermission 方法没有区分文件的公开/私人属性
查询过滤不足：pageFiles 方法在列表查询时未排除他人的私人文件
安全隐患
❌ 用户A上传的私人文件，同部门的用户B也能看到
❌ 部门管理员可以查看所有本部门用户的私人文件
❌ 隐私数据可能被未授权人员访问

✅ 修改内容
修改点 1：增强权限检查逻辑
位置：第 475-506 行 方法：checkFilePermission(File file, User user)
修改前代码

private void checkFilePermission(top.tqx.demo_1.entity.File file, top.tqx.demo_1.entity.User user) {
    Integer userType = user.getUserType();
    Long currentUserId = user.getId();
    Long currentDeptId = user.getDeptId();

    if (userType.equals(CommonConstant.RoleType.SUPER_ADMIN)) {
        return;
    }
    
    if (userType.equals(CommonConstant.RoleType.DEPT_ADMIN)) {
        if (!file.getDeptId().equals(currentDeptId)) {
            throw new RuntimeException("无权限查看此文件");
        }
        return;
    }
    
    if (userType.equals(CommonConstant.RoleType.NORMAL_USER)) {
        if (!file.getDeptId().equals(currentDeptId)) {
            throw new RuntimeException("无权限查看此文件");
        }
        if (!file.getUploadUserId().equals(currentUserId)) {
            throw new RuntimeException("无权限查看此文件");
        }
        if (file.getAuditStatus() != null && file.getAuditStatus() == 0) {
            throw new RuntimeException("文件待审核，暂时无法查看");
        }
    }
修改后代码

private void checkFilePermission(top.tqx.demo_1.entity.File file, top.tqx.demo_1.entity.User user) {
    Integer userType = user.getUserType();
    Long currentUserId = user.getId();
    Long currentDeptId = user.getDeptId();

    // 超级管理员拥有所有权限
    if (userType.equals(CommonConstant.RoleType.SUPER_ADMIN)) {
        return;
    }
    
    // 【新增】私人文件权限检查：只有上传者本人可访问
    if (file.getIsPublic() != null && file.getIsPublic() == 0) {
        if (!file.getUploadUserId().equals(currentUserId)) {
            throw new RuntimeException("无权限查看此私人文件");
        }
        return;
    }
    
    // 公开文件的部门权限检查
    if (userType.equals(CommonConstant.RoleType.DEPT_ADMIN)) {
        if (!file.getDeptId().equals(currentDeptId)) {
            throw new RuntimeException("无权限查看此文件");
        }
        return;
    }
    
    if (userType.equals(CommonConstant.RoleType.NORMAL_USER)) {
        if (!file.getDeptId().equals(currentDeptId)) {
            throw new RuntimeException("无权限查看此文件");
        }
        if (file.getAuditStatus() != null && file.getAuditStatus() == 0) {
            throw new RuntimeException("文件待审核，暂时无法查看");
        }
    }
    
关键改进
✅ 优先检查私人文件：在任何其他权限判断之前，先判断是否为私人文件 ✅ 严格所有者验证：私人文件必须满足 uploadUserId == currentUserId ✅ 提前返回机制：私人文件检查通过后直接返回，避免后续逻辑干扰

修改点 2：增强列表查询过滤
位置：第 48-87 行 方法：pageFiles(Integer pageNum, Integer pageSize, String fileName, User user)
修改前代码

```
if (userType.equals(CommonConstant.RoleType.SUPER_ADMIN)) {
    wrapper.eq(File::getStatus, CommonConstant.STATUS_ENABLE);
} else if (userType.equals(CommonConstant.RoleType.DEPT_ADMIN)) {
    wrapper.eq(File::getStatus, CommonConstant.STATUS_ENABLE);
    wrapper.and(w -> w.eq(File::getDeptId, currentDeptId)
            .or().eq(File::getUploadUserId, currentUserId));
} else if (userType.equals(CommonConstant.RoleType.NORMAL_USER)) {
    wrapper.eq(File::getStatus, CommonConstant.STATUS_ENABLE);
    wrapper.ne(File::getAuditStatus, 0);
    wrapper.and(w -> w.eq(File::getDeptId, currentDeptId)
            .or().eq(File::getUploadUserId, currentUserId));
}

```

修改后代码

```
if (userType.equals(CommonConstant.RoleType.SUPER_ADMIN)) {
    wrapper.eq(File::getStatus, CommonConstant.STATUS_ENABLE);
} else if (userType.equals(CommonConstant.RoleType.DEPT_ADMIN)) {
    wrapper.eq(File::getStatus, CommonConstant.STATUS_ENABLE);
    wrapper.and(w -> w.eq(File::getDeptId, currentDeptId)
            .or().eq(File::getUploadUserId, currentUserId));
    // 【新增】排除他人私人文件
    wrapper.and(w -> w.ne(File::getIsPublic, 0)
            .or().eq(File::getUploadUserId, currentUserId));
} else if (userType.equals(CommonConstant.RoleType.NORMAL_USER)) {
    wrapper.eq(File::getStatus, CommonConstant.STATUS_ENABLE);
    wrapper.ne(File::getAuditStatus, 0);
    wrapper.and(w -> w.eq(File::getDeptId, currentDeptId)
            .or().eq(File::getUploadUserId, currentUserId));
    // 【新增】排除他人私人文件
    wrapper.and(w -> w.ne(File::getIsPublic, 0)
            .or().eq(File::getUploadUserId, currentUserId));
}

```

SQL 逻辑说明
新增的过滤条件生成的 SQL 逻辑为：

```
-- 对于部门管理员和普通用户
WHERE ... 
  AND (
    is_public != 0  -- 非私人文件
    OR upload_user_id = currentUserId  -- 或者是自己上传的文件
  )

```

关键改进
✅ 数据库层过滤：在查询阶段就排除他人私人文件，提升性能和安全性 ✅ 双重保护：既在查询层过滤，又在访问层检查，形成纵深防御 ✅ 保留自身访问：用户可以查看自己的私人文件（包括已上传的私人文件）