猿问

如何检查 SecurityManager 中的调用者类来源?

我有一个用于受信任的应用程序代码的 ClassLoader 和一个用于用户提交的(不受信任的)代码的单独的 ClassLoader。


我希望安全管理器限制用户提交的代码。如何从 SecurityManager 中检查调用方来源?查看伪代码:


System.setSecurityManager(new SecurityManager() {

    public void checkPermission(Permission permission) {

        if (/*caller class is not loaded by the trusted classloader*/) {

            throw new SecurityException("You do not have permissions.");

        }

    }

});

我已经尝试过的:


StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE).getCallerClass().getClassLoader()首先检查权限,以便它给出堆栈溢出异常。


Thread.currentThread().getStackTrace()[2].getClassLoaderName()是不安全的,因为它只提供类加载器名称而不是类对象,如果不受信任的加载器的规范名称与受信任的加载器相同,那么这是一个安全问题。


不负相思意
浏览 121回答 2
2回答

慕姐8265434

首先,SecurityManager 有一个受保护的方法getClassContext()。您的代码如下所示:System.setSecurityManager(new SecurityManager() {    public void checkPermission(Permission permission) {        Class<?> caller = getClassContext()[1];        ClassLoader ccl = caller.getClassLoader();        if (ccl != null || ccl != getClass().getClassLoader()) {            throw new SecurityException("You do not have permissions.");        }    }});其次,如果要使用 a StackWalker,建议您复用StackWalker实例:StackWalker walker = StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);System.setSecurityManager(new SecurityManager() {    public void checkPermission(Permission permission) {        Class<?> caller = walker.getCallerClass();        ClassLoader ccl = caller.getClassLoader();        if (ccl != null || ccl != getClass().getClassLoader()) {            throw new SecurityException("You do not have permissions.");        }    }});第三,这很可能不会做你想做的。安全检查在整个 JDK 中完成,因此调用者可能在任意数量的堆栈级别之外,需要您检查整个堆栈(提示:在您第二次访问堆栈中的 SecurityManager 时中断)。相反,定义一个策略(创建一个 java 策略文件),您可以在其中授予您的代码所有权限并使用 java.lang.SecurityManager。如果无法编写您自己的策略文件,您也可以使用Policy.setPolicy()安装您自己的java.security.Policy.一些实现 a 的提示java.security.Policy:覆盖implies和两种getPermissions方法。严重地。赶上你自己ProtectionDomain的政策类。( private static final ProtectionDomain MY_PD = MyPolicy.class.getProtectionDomain())如果检查是针对您自己的 ProtectionDomain,请使用快速路径。

慕后森

我找到了一个临时解决方案,但它并不完美:System.setSecurityManager(new SecurityManager() {&nbsp; &nbsp; public void checkPermission(Permission permission) {&nbsp; &nbsp; &nbsp; &nbsp; Class<?> caller = SecurityManager.class;&nbsp; &nbsp; &nbsp; &nbsp; Class<?>[] classContext = this.getClassContext();&nbsp; &nbsp; &nbsp; &nbsp; int loopAmount = 0;&nbsp; &nbsp; &nbsp; &nbsp; while (caller.getCanonicalName() == null&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;|| !caller.getCanonicalName().startsWith("nl")) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; caller = classContext[loopAmount];&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; loopAmount++;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; if (caller.getClassLoader() != trustedClassLoader) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; throw new SecurityException("You do not have permissions.");&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }});所有不受信任的类的规范名称都必须以“nl”开头。这是 afaik 从类上下文中获取调用者类的唯一方法,因为调用者类的数组位置未知,上下文数组的最后一个元素始终是具有 main 方法的类。
随时随地看视频慕课网APP

相关分类

Java
我要回答