核心是阻断路径穿越,需白名单、规范化和权限隔离三重控制:先解码标准化路径,再用startswith校验是否在安全根目录内;禁用拼接,改用resolve和预设映射;检查符号链接与文件权限;记录非法访问并告警。

核心是阻断路径穿越,同时确保文件访问范围严格限定在预期目录内。光过滤 ../ 不够,必须结合白名单、规范化和权限隔离三重控制。
严格校验并规范化输入路径
不能只做一次字符串替换,要先解码再标准化路径,再比对是否落在安全根目录下。
- 使用
Paths.get().normalize()处理用户传入的文件名,自动消除../、./和冗余分隔符 - 将结果路径转为绝对路径,并用
startsWith(secureBasePath)强制校验是否仍在授权目录内(如/var/www/uploads/) - 拒绝含空字节(
%00)、非ASCII路径分隔符(如%5c或..\)的请求
避免拼接路径,改用白名单机制
对业务场景明确的文件访问,优先放弃动态路径拼接,改用映射表或枚举值控制。
Java JDK 25 来自 OpenJDK 官方归档,版本为 JDK 25,本条下载地址已指向官方 Windows x64 zip 安装包直链,适合调试旧项目或兼容旧版 Java 运行环境。
- 例如下载头像时,参数只接受预设 ID(如
avatar_123),后端查数据库获取对应真实文件名和存储位置 - 静态资源访问统一走 Spring 的
ResourceHttpRequestHandler,配合setLocations指定唯一可访问目录 - 禁用
File(path + userInput)这类直接拼接方式,改用Paths.get(baseDir).resolve(fileName)
限制文件操作的权限与上下文
即使路径合法,也要防止符号链接跳转或越权读取。
- 调用
Files.isRegularFile()和Files.isReadable()双重确认目标是否为普通可读文件 - 检查文件是否为符号链接(
Files.isSymbolicLink()),若存在则拒绝访问 - 应用运行账户仅赋予最小必要权限——比如只读
/app/resources/,不给/etc/或/home/任何权限
日志与监控兜底
异常路径访问行为本身就有风险,需记录并告警。
- 记录所有被拦截的非法路径尝试,包括原始参数、客户端 IP 和时间戳
- 对高频失败请求(如 1 分钟内 5 次含
../的下载)触发限流或临时封禁 - 定期扫描代码中所有
FileInputStream、Files.readAllBytes、getResourceAsStream等敏感调用点,确认是否加了上述防护
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










