【EasyPan】项目常见问题解答(自用&持续更新中…)汇总版
一、loadDataList
方法概览
@RequestMapping("/loadFileList")
@GlobalInterceptor(checkParams = true, checkLogin = false)
public ResponseVO loadDataList(HttpSession session,
@VerifyParam(required = true) String shareId,
String filePid) {
SessionShareDto shareSessionDto = checkShare(session, shareId);
FileInfoQuery query = new FileInfoQuery();
if (!StringTools.isEmpty(filePid) && !Constants.ZERO_STR.equals(filePid)) {
fileInfoService.checkRootFilePid(
shareSessionDto.getFileId(),
shareSessionDto.getShareUserId(),
filePid
);
query.setFilePid(filePid);
} else {
query.setFileId(shareSessionDto.getFileId());
}
query.setUserId(shareSessionDto.getShareUserId());
query.setOrderBy("last_update_time desc");
query.setDelFlag(FileDelFlagEnums.USING.getFlag());
PaginationResultVO result = fileInfoService.findListByPage(query);
return getSuccessResponseVO(convert2PaginationVO(result, FileInfoVO.class));
}
二、checkRootFilePid
方法深度分析
@Override
public void checkRootFilePid(String rootFilePid, String userId, String fileId) {
if (StringTools.isEmpty(fileId)) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
if (rootFilePid.equals(fileId)) {
return;
}
checkFilePid(rootFilePid, fileId, userId);
}
核心安全校验逻辑(递归实现)
private void checkFilePid(String rootFilePid, String fileId, String userId) {
FileInfo fileInfo = this.fileInfoMapper.selectByFileIdAndUserId(fileId, userId);
if (fileInfo == null) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
if (Constants.ZERO_STR.equals(fileInfo.getFilePid())) {
throw new BusinessException(ResponseCodeEnum.CODE_600);
}
if (fileInfo.getFilePath().equals(rootFilePid)) {
return;
}
checkFilePid(rootFilePid, fileInfo.getFilePid(), userId);
}
三、安全防护矩阵
攻击类型 | 防御措施 | 对应代码位置 |
---|
路径遍历 | 递归验证父目录归属 | checkFilePid 递归调用 |
越权访问 | 用户ID+文件ID双重验证 | selectByFileIdAndUserId |
恶意参数 | 空值检查和根目录特殊处理 | 首个if 判断块 |
共享根目录 | 显式拦截根目录分享场景 | ZERO_STR.equals 检查 |
分层防御机制
防御层级 | 检查点 | 拦截场景 | 典型攻击示例 |
---|
L1 | 空值检查 | 空参数攻击 | fileId=null |
L2 | 快速路径匹配 | 直接访问分享根目录 | 正常访问分享链接 |
L3 | 数据库存在性检查 | 伪造文件ID | fileId=123456 (不存在ID) |
L4 | 用户归属验证 | 越权访问其他用户文件 | 修改userId参数 |
L5 | 根目录保护 | 尝试分享整个网盘 | filePid=0 |
L6 | 路径匹配验证 | 目录跳转攻击 | ../../../etc/passwd |
L7 | 递归父目录验证 | 深层嵌套越权 | 多级目录伪造 |
四、方法调用关系
loadDataList
├─ checkShare (验证分享有效性)
└─ checkRootFilePid
├─ 直接返回 (当fileId=rootFilePid)
└─ checkFilePid (递归验证)
├─ 数据库查询验证
├─ 根目录拦截
└─ 递归向上验证
五、典型异常处理流程
1. 客户端请求: /loadFileList?shareId=abc&filePid=xyz
2. 服务端校验:
- checkRootFilePid("root123", "user1", "xyz")
→ 触发checkFilePid递归
→ 第三次递归发现filePid="hij"不存在
3. 异常抛出:
BusinessException(
code=600,
msg="参数错误",
debugMsg="文件hij不存在或不属于用户user1"
)
4. 全局异常处理器转换为:
{code:600, info:"参数错误", status:"error"}