You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义策略文件的Java SecurityManager未按预期工作

Java SecurityManager权限验证异常排查

我正在学习Java SecurityManager的工作机制,编写了测试代码验证,但始终抛出异常。

测试代码

public class FilePermissionChecker2 {
    public static void main(String[] args) {
        String filePath = "c:\\file.txt";
        Permission perm = new FilePermission(filePath, "read,write");
        PermissionCollection perms = perm.newPermissionCollection();

        perms.add(perm);

        boolean hasPermission = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
            @Override
            public Boolean run() {
                // 检查文件权限
                File file = new File(filePath);
                if (file.exists() && file.canRead() && file.canWrite()) {
                    return true;
                } else {
                    return false;
                }
            }
        }, new AccessControlContext(
                new ProtectionDomain[]{
                        new ProtectionDomain(null, perms)
                }
        ));

        if (hasPermission) {
            System.out.println("拥有必要的文件权限。");
        } else {
            System.out.println("没有必要的文件权限。");
        }

    }
}

自定义策略文件

grant {
    permission java.io.FilePermission "c:\\file.txt", "read, write";
};

VM参数设置

-Djava.security.manager -Djava.security.policy=...pathToPolicy...\policy\custom.policy

异常信息

Exception in thread "main" java.security.AccessControlException: access denied ("java.io.FilePermission" "c:\file.txt" "read")

我预期SecurityManager会基于自定义策略和代码中的权限取交集进行检查,但实际未生效,请问问题出在哪里?

已尝试操作:

  • 调整自定义策略的多种组合
  • 调整FilePermissions的多种组合

问题分析与解决方案

  1. 策略文件路径验证
    确保VM参数中-Djava.security.policy的路径正确:

    • Windows下路径需使用正斜杠(/)或双反斜杠(\\),如果路径包含空格,需要用引号包裹,例如:-Djava.security.policy="C:\\Program Files\\policy\\custom.policy"
    • 优先使用绝对路径,避免相对路径因IntelliJ工作目录不一致导致的加载失败。
  2. JDK版本兼容性
    JDK 17及以上版本中SecurityManager已被废弃,虽然通过-Djava.security.manager仍可启用,但存在兼容性问题。建议切换到JDK 8或11进行测试。

  3. 代码逻辑调整
    原代码通过File.exists()/canRead()/canWrite()触发权限检查,这类方法可能隐含额外的系统检查。建议直接通过AccessController.checkPermission验证权限,逻辑更明确:

    @Override
    public Boolean run() {
        try {
            AccessController.checkPermission(perm);
            // 若权限通过,再执行文件操作
            File file = new File(filePath);
            return file.exists() && file.canRead() && file.canWrite();
        } catch (AccessControlException e) {
            return false;
        }
    }
    
  4. 权限集合有效性验证
    在代码中添加日志,确认PermissionCollection是否正确包含权限:

    System.out.println("权限集合内容:" + perms.toString());
    

    输出应包含(java.io.FilePermission c:\file.txt read,write),否则说明权限添加逻辑有误。

  5. 启用权限调试
    添加VM参数-Djava.security.debug=access,查看详细的权限检查日志,可明确是哪个ProtectionDomain拒绝了权限,以及检查的具体规则。


内容的提问来源于stack exchange,提问作者Štefan Starosta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 01:54:49