Java原生SecurityManager可限制脚本磁盘读写,但仅适用于Java 8–17;需JVM启动时启用策略文件,通过FilePermission精确授权目录,配合运行时路径校验增强安全;Java 21+已移除该机制,应转向容器隔离或API拦截等替代方案。

明确启用安全管理器并绑定策略文件
仅声明类或调用 System.setSecurityManager() 不足以生效,必须配合策略文件(`.policy`)且 JVM 启动时显式启用:
- 启动命令中使用双等号
==完全覆盖默认策略,避免权限意外放宽:java -Djava.security.manager -Djava.security.policy==/path/to/restrict-disk.policy MyApp - 策略文件路径需由 JVM 进程可读(例如不放在受限目录下)
- 确保脚本执行环境(如
ScriptEngineManager)运行在同一线程上下文,否则权限检查可能不触发
策略文件中精准控制 FilePermission
磁盘读写由 java.io.FilePermission 控制,必须显式拒绝或最小化授予——默认禁止,不配置即无权限:
- 完全禁止所有磁盘读写(最严格):
grant { permission java.io.FilePermission ">", "read,write,delete,execute"; };
⚠️ 注意:这行实际是「授予」全部权限;要禁止,就**不写任何 FilePermission 条目**,或只授极小范围 - 仅允许访问指定安全目录(推荐):
grant { permission java.io.FilePermission "/tmp/myapp/-", "read,write,delete"; };
其中/tmp/myapp/-表示该目录及其子目录下所有文件 - 显式拒绝敏感路径(策略文件本身不支持 deny 语法,只能靠「不授予 + 默认禁止」实现;若需更强隔离,应结合 OS 层限制)
配合代码层防御增强实效性
策略文件是静态规则,而未知脚本可能绕过路径检查(如通过符号链接、相对路径跳转)。建议在关键操作前补充运行时校验:
- 重写
checkRead(String file)和checkWrite(String file)方法,做白名单路径匹配:if (!file.startsWith("/tmp/myapp/")) { throw new SecurityException("Blocked: " + file); } - 对
File.getCanonicalPath()校验,防止../跳出授权目录 - 若脚本通过
Runtime.exec()调用外部命令,还需配置java.lang.RuntimePermission "exec"并严格限制
替代方案(尤其面向 Java 17+ 或生产环境)
因 SecurityManager 已废弃,长期应转向更可靠机制:
立即学习“Java免费学习笔记(深入)”;
- 用容器(Docker)挂载只读根文件系统,并仅将必要目录以
ro或rw方式 bind mount - JVM 启动参数限制本地库和文件系统访问:
-XX:+DisableAttachMechanism -Djdk.io.permissionsUseCanonicalPath=false - 在脚本引擎封装层统一拦截
Files.readAllBytes、Files.write等 API,强制走受控 I/O 通道


















