java - 如何在 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()
是不安全的,因为它只给出类加载器名称而不是类对象,如果不受信任的加载器的规范名称与受信任的加载器相同,那么这是一个安全问题。
解决方案
首先,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
的 Policy 课程。(private static final ProtectionDomain MY_PD = MyPolicy.class.getProtectionDomain()
) - 如果检查是针对您自己的 ProtectionDomain,请使用快速路径。在这种情况下不要调用其他代码,否则你可能会得到一个 StackOverflow。
推荐阅读
- git - 具有多个提交的 Git 补丁,最后一个未应用
- android - viewpager 隐藏在某些华为和荣耀手机上
- algorithm - 如何求时间复杂度和大O?
- python - 如何在 Powershell 中使用 Tree 压缩文件
- flutter - 颤动取消选择 RadioListTile 按钮
- python - 删除目录 - 测试文件繁忙错误
- python-3.x - 如何在python中构建任意深度的动态树?
- snakemake - 如何在snakemake中设置绑定内存限制
- python-3.x - 如何在 boto3 dynamodb 中查询 json 文件?
- java - 将数组向右移动一个插槽