[Java/JVM/安全] ProtectionDomain : Java 安全模型的核心组件

概述: ProtectionDomain : Java 安全模型的核心组件

组件简介

  • java.security.ProtectionDomainJava 安全模型中的核心概念,主要用于封装代码的“来源”和“权限”,实现细粒度的访问控制。
  • 自 JDK 1.2 起即支持此组件

主要作用

1. 定义代码的“来源”与“签名者”

  • 来源(CodeSource):由代码的位置(URL)数字证书(签名者)组成,用于标识“这段代码是谁写的、从哪里加载的”。
  • 例如:一个从 https://example.com/ 下载的、被某公司签名的 JAR 包,其 ProtectionDomain 会记录这些元数据。

2. 绑定代码的权限(Permissions)

  • ProtectionDomain 内部包含一个 PermissionCollection(权限集合),明确指定这段代码允许做什么(如读写文件、访问网络等)。
  • 当代码尝试敏感操作时(如读取 /etc/passwd),Java 安全机制会检查该代码对应的 ProtectionDomain 是否有对应权限。

3. 实现“沙箱”隔离

  • 不同来源的代码拥有不同权限:例如浏览器中的 Applet(已过时)或企业应用中的插件,通过为每个 ProtectionDomain 分配不同权限,实现最小权限原则

  • 示例场景

    • 本地系统库的 ProtectionDomain 拥有所有权限(AllPermission)。
    • 远程下载的未签名代码的 ProtectionDomain 只有有限权限(如无法访问本地文件)。

4. 支持动态策略(Policy)

  • Java 的 Policy 类(通过 java.security.policy 文件配置)会根据 ProtectionDomainCodeSource 动态分配权限。

  • 例如:

grant signedBy "trusted_vendor", codeBase "https://example.com/*" {
    permission java.io.FilePermission "/tmp/*", "read,write";
};

5. 与 AccessController 协同工作

  • 当代码调用 AccessController.checkPermission(...) 时,JVM 会遍历当前调用栈中所有 ProtectionDomain只要有一个权限不足,就抛出 AccessControlException

  • 这种机制防止了“权限提升攻击”(如不可信代码通过调用可信代码的敏感方法绕过限制)。

代码示例

// 获取当前类的 ProtectionDomain
ProtectionDomain domain = MyClass.class.getProtectionDomain();
System.out.println("CodeSource: " + domain.getCodeSource());
System.out.println("Permissions: " + domain.getPermissions());

最佳实践

CASE 获取本JAR包的所处目录

    /**
     * 获取应用程序JAR包所处路径
     * @param applicationClazz 应用程序的 Class 类
     *     1. 不能是 JDK 的 Class 类,例如: Object.class , Class.class , ... (将报错)
     * @return
     *   "D:\Workspace\CodeRepositories\xxx-platform\xxx-sdk\xxx-sdk-helper\target" (源码工程在运行时的获取结果)
     *   "D:\Workspace\Projects\XXX-Project\xxx-sdk-helper-1.0.0-SNAPSHOT-jar-with-dependencies.jar" (JAR包在运行时的获取结果)
     */
    public static String getApplicationJarDirectory(Class applicationClazz){
        // 获取当前类的 ProtectionDomain
        ProtectionDomain domain = applicationClazz.getProtectionDomain();//只能是应用工程的自定义类,不能是 jdk 的 类(如: Object.class , Class.class)
        URL location = domain.getCodeSource().getLocation();

        File jarFile = null;

        try {
            // 转换为文件路径
            jarFile = new File(location.toURI());
            //String jarDirectory = jarFile.getParent(); // JAR 所在目录
        } catch (Exception exception) {
            log.error("get current jar path fail !exception:", exception);
        }
        log.info("current jar path: {}", jarFile.getAbsolutePath());//"file:/D:/Workspace/CodeRepositories/xxx-platform/xxx-sdk/xxx-sdk-helper/target/classes/" or "D:\Workspace\Projects\XXX-Project\xxx-sdk-helper-1.0.0-SNAPSHOT-jar-with-dependencies.jar"
        return jarFile == null ? null : jarFile.getParentFile().getAbsolutePath();
    }

总结

  • ProtectionDomain 是 Java 安全架构的“守门员”,通过将代码来源、签名者与权限绑定,确保只有受信任的代码才能执行敏感操作,是实现细粒度安全策略的基础

Y 推荐文献

X 参考文献

posted @ 2025-07-22 09:45  千千寰宇  阅读(79)  评论(0)    收藏  举报