首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在动态类加载时保护Java应用程序?

如何在动态类加载时保护Java应用程序?
EN

Stack Overflow用户
提问于 2018-08-24 09:28:38
回答 2查看 2K关注 0票数 4

我有一个Java/Scala应用程序,它执行磁盘IO并动态加载用户提交的类。动态类在它们自己的ClassLoaders下运行。

在加载这些类时应该考虑哪些安全问题,以确保它们没有删除磁盘文件或执行任何恶意操作的权限,并且只是在执行内存中的操作?

我到目前为止做了什么,

  • Regex检查以删除与java.io.*java.nio.*java.lang.reflectjava.lang.Runtime.*相关的导入。我试图看看这些导入是否可以直接从类路径中删除,而不是执行regex操作。
  • 为动态加载类的实例的每次执行设置超时。
  • 编写测试加载1000 s的类以动态加载以检查PermGen问题,并且没有内存泄漏。

另一种选择是在它们自己的JVM进程中运行它们,并为每个进程设置文件系统(Linux)级别的权限,但这并不适合我的解决方案,因为我需要它们共享线程安全的内存对象。

有人能不能建议一下,如果我走上了正确的轨道,还应该考虑些什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-08-25 12:56:43

正如@Kayaman所说,您应该尝试使用SecurityManager处理这些动态类-- permissions,这里有一个很小的例子来演示这一点,也许这对您有帮助。

1.创建动态类策略文件,这将用于限制权限,例如my.policy

代码语言:javascript
复制
grant {
   permission java.io.FilePermission "*", "read";
};

上述策略将为任何文件启用读取文件

2.创建自定义策略文件,用于处理具有权限验证规则的动态类

代码语言:javascript
复制
class MyPolicy extends Policy {
    //custom classes with policy mapping
    private final Map<String, Policy> plugins;

    MyPolicy(Map<String, Policy> plugins) {
        this.plugins = plugins;
    }

    @Override
    public boolean implies(ProtectionDomain domain, Permission permission) {
        CodeSource codeSource = domain.getCodeSource();
        if (codeSource == null) {
            return false;
        }

        URL location = codeSource.getLocation();
        if (location != null) {
            //get the custom plugin policy rules and validate the permissions
            Policy plugin = this.plugins.get(location.getFile());
            if (plugin != null) {
                return plugin.implies(domain, permission);
            }
        }
        return defaultSystemPermissions().implies(permission);
    }
    private PermissionCollection defaultSystemPermissions() {
        Permissions permissions = new Permissions();
        permissions.add(new AllPermission()); // this will set the application default permissions, in there we enable all 
        return permissions;
    }
}

在上面的代码中,将验证权限 of 动态类,如果缺乏相应的权限,则在运行时将抛出:

代码语言:javascript
复制
java.security.AccessControlException: access denied ("java.io.FilePermission" "test.txt" "read")

在那里还启用了默认应用程序的所有权限,也许应该在实际场景中更多地考虑它。

3.为您的SecurityManager动态策略安装setPolicy并安装它。

代码语言:javascript
复制
        // load the dynamic classes
        URL pluginClass = new File("./myplugin").toURI().toURL();
        // read my plugin security policy
        URIParameter myPolicyPath = new URIParameter(MyClass.class.getResource("/my.policy").toURI());
        Policy policy = Policy.getInstance("JavaPolicy", myPolicyPath);
        MyPolicy myPolicy = new MyPolicy(ImmutableMap.of(pluginClass.getPath(), policy));
        Policy.setPolicy(myPolicy);
        // install the security manager
        System.setSecurityManager(new SecurityManager());

4.完整的例子: TestClass:

代码语言:javascript
复制
public class TestClass {
    public void foobar() throws IOException {
        Path path = Paths.get("test.txt");
        String lines = Files.readAllLines(path).stream().collect(Collectors.joining(","));

        System.out.println(lines);
    }
}

跑步者:

代码语言:javascript
复制
public static void main(String[] args) throws Exception{
    // create a new url class loader, this can be used to load a jar or classes directory
    URL pluginClass = new File("./myplugin").toURI().toURL();
    URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{pluginClass}, MyClass.class.getClassLoader());

    // load a dynamic TestClass class
    Class loadedMyClass = urlClassLoader.loadClass("TestClass");

    // read my plugin security policy
    URIParameter myPolicyPath = new URIParameter(MyClass.class.getResource("/my.policy").toURI());
    Policy policy = Policy.getInstance("JavaPolicy", myPolicyPath);
    MyPolicy myPolicy = new MyPolicy(ImmutableMap.of(pluginClass.getPath(), policy));
    Policy.setPolicy(myPolicy);
    // install the security manager
    System.setSecurityManager(new SecurityManager());


    System.out.println("Loaded class: " + loadedMyClass.getName());

    Object myClassObject = loadedMyClass.getConstructor().newInstance();
    Method method = loadedMyClass.getMethod("foobar");
    System.out.println("Invoked method: " + method.getName());
    method.invoke(myClassObject);

}

参考资料:

https://docs.oracle.com/javase/tutorial/essential/environment/security.html

票数 2
EN

Stack Overflow用户

发布于 2018-08-24 09:35:44

与其侵入您自己的解决方案,不如使用内置的SecurityManager来处理针对不同任务的各种不同权限。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52001421

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档