java文件操作限制敏感目录访问的核心是启用securitymanager并配合策略文件精确控制filepermission,jvm在每次操作前自动检查权限,未授权即抛出accesscontrolexception;策略文件定义codebase、permission及target name,通过默认拒绝和白名单机制限制/etc/、/root/等路径;需用-djava.security.manager和-djava.security.policy==指定启动参数;java 17+已弃用该机制。

Java 文件操作中限制对敏感系统目录的访问,核心是启用 SecurityManager 并配合策略文件(policy file)精确控制 java.io.FilePermission。这不是靠代码里手动判断路径,而是让 JVM 在每次文件操作前自动检查权限,未授权即抛出 AccessControlException(不是 SecurityException,后者是 SecurityManager 自身抛出的异常类型,而权限检查失败实际触发的是前者)。
关键不在于“怎么写 if 判断”,而在于“怎么让 JVM 主动拦住”。
用策略文件声明哪些路径允许访问
策略文件(如 my.policy)定义了谁(codeBase)、能做什么(permission)、对什么资源(target name)。限制敏感目录,就是不授予权限,或显式 deny。
例如,禁止读写 /etc/、/root/、C:Windows 等目录:
// my.policy
// 默认不授予权限 —— Java 安全模型是“默认拒绝”
// 只给可信代码开白名单
grant codeBase "file:/opt/myapp/app.jar" {
// 允许应用读写自己工作目录
permission java.io.FilePermission "/opt/myapp/data/-", "read,write,delete";
// 允许读取配置,但不允许写
permission java.io.FilePermission "/opt/myapp/conf/*", "read";
};
// 对第三方 JAR 或所有未明确授权的代码,不给任何文件权限
// 即:访问 /etc/passwd、/root/.ssh 等会直接失败
注意:
-
"/etc/-"表示/etc/目录及其所有子路径; -
"read,write,delete"是组合权限,可按需拆分; - 没有 grant 规则匹配的代码,默认无任何文件权限。
启动时加载策略并启用 SecurityManager
仅写 policy 文件没用,必须让 JVM 加载它,并启用安全管理器:
java -Djava.security.manager
-Djava.security.policy==/path/to/my.policy
-jar myapp.jar
⚠️ 注意:
- 双等号
==表示完全覆盖默认策略(推荐),单等号=是追加; - Java 17+ 已弃用 SecurityManager,Java 21 起彻底移除 —— 此方案仅适用于 Java 8–16;
- 应用内不可调用
System.setSecurityManager(null),否则策略失效。
针对特定敏感路径做运行时拦截(补充手段)
如果策略文件不够灵活(比如要动态识别 .env、application-secret.yml),可自定义 SecurityManager,在 checkRead/checkWrite 中加逻辑:
public class StrictFileSecurityManager extends SecurityManager {
private static final Set<string> SENSITIVE_PATHS = Set.of(
"/etc/passwd", "/etc/shadow", "/root/", "C:\Windows\System32\"
);
@Override
public void checkRead(String file) {
if (file == null) return;
for (String prefix : SENSITIVE_PATHS) {
if (file.startsWith(prefix) ||
file.replace("\", "/").startsWith(prefix.replace("\", "/"))) {
throw new SecurityException("Blocked read access to: " + file);
}
}
}
@Override
public void checkWrite(String file) {
// 类似处理
}
}</string>
然后启动时指定:
-Djava.security.manager=StrictFileSecurityManager
⚠️ 注意:自定义 SecurityManager 不能替代策略文件,它只是增强层;策略文件仍是权限决策的权威来源。
常见误区提醒
- ❌ 不要试图在
FileInputStream构造前手动检查路径 —— 这容易被绕过(如符号链接、../跳转、NIO 的Path.resolve()); - ❌ 不要用
System.getProperty("user.home")拼路径再检查 —— 权限检查应在 JVM 层统一触发; - ✅ 真正生效的是
FilePermission的 target name 匹配逻辑,JVM 内部会规范化路径(如消除..、.),所以策略里写/home/*/是有效的; - ✅ 若用模块化(JPMS),还需注意
--add-opens不影响 SecurityManager 检查,二者正交。
不复杂但容易忽略。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











