SecurityManager通过在Java运行时层拦截文件I/O API调用并执行checkRead/checkWrite等权限校验来限制文件访问,依赖FilePermission策略控制路径粒度,不作用于操作系统内核或JNI调用。

SecurityManager 限制代码对文件的访问,核心在于拦截 JVM 对底层文件操作的调用,并通过权限检查决定是否放行。它不直接修改操作系统级的文件句柄或内核策略,而是作用于 Java 运行时层,对 java.io 和 java.nio 包中敏感 API 的调用进行前置校验。
哪些文件操作会被 SecurityManager 拦截
只要涉及以下行为,且当前启用了 SecurityManager,JVM 就会在执行前调用对应 check 方法:
-
读取文件或目录:调用
FileInputStream、Files.readAllBytes()、File.list()等,触发checkRead(String file)或checkRead(FileDescriptor fd) -
写入文件或创建新文件:如
FileOutputStream、Files.write()、File.createNewFile(),触发checkWrite(String file)或checkWrite(FileDescriptor fd) -
删除或重命名文件:调用
File.delete()或Files.move(),触发checkDelete(String file) -
列出目录内容:
File.list()或Files.newDirectoryStream()触发checkRead(String dir)(因为需读取目录元数据)
底层拦截发生在 Java 类库的“安全敏感点”
JDK 中关键 I/O 类(如 FileInputStream、FileOutputStream、File、Files)在构造或执行关键动作前,会显式调用:
SecurityManager sm = System.getSecurityManager();
if (sm != null) sm.checkRead(path); // 或 checkWrite、checkDelete 等
这个调用链最终进入 checkPermission(new FilePermission(path, action)),再由 AccessController 根据当前策略(policy 文件或自定义逻辑)判定是否允许。没有策略匹配或显式拒绝,就抛出 SecurityException,操作终止。
Policy 文件如何精确控制路径权限
权限粒度由 FilePermission 的 target_name 决定,支持通配符和层级语义:
-
"F:/tmp/-":允许对F:\tmp及其所有子目录、文件执行指定 action(如"read,write") -
"F:/config.properties":仅针对该单个文件 -
"F:/data/*":允许F:\data下一级的所有文件(不含子目录) -
"<<ALL FILES>>":特殊字符串,表示所有文件路径(慎用)
action 字符串必须严格匹配,比如只写 "read" 就不能执行写操作;多个 action 用逗号分隔:"read,write,delete"。
绕过限制的常见误区与边界
注意:SecurityManager 无法控制所有文件相关行为:
-
内存映射文件(MappedByteBuffer):若底层使用
FileChannel.map(),仍会触发checkRead/checkWrite,但映射后对内存页的读写不再受检 -
Native 层文件操作:通过 JNI 直接调用
fopen、CreateFileW等,完全绕过 JVM 安全机制 -
临时文件与系统属性:
System.getProperty("java.io.tmpdir")返回路径本身不触发检查,但后续用该路径构造File对象就会被拦 -
类路径加载:
ClassLoader.getResource()不走FilePermission检查,而是依赖RuntimePermission("getClassLoader")等其他权限

















