- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
您好 SecurityManager 专家 ;-)
我编写了一个小型插件框架,它使用单独的隔离类加载器加载插件。要成功取消部署插件,重要的是要确保应用程序不保留对插件类加载器加载的类的引用。
Java 中有一个称为关闭 Hook 的功能,它使客户端代码能够注册一个线程,该线程在 JVM 被请求关闭时执行。这意味着 JVM 可能会持有对插件类加载器加载的类的引用。
我的第一次尝试是安装一个拒绝添加关闭 Hook 的 SecurityManager。这完全有效并拒绝所有添加关闭 Hook 的尝试。有趣的是,我意识到,想要添加关闭 Hook 的不是插件本身。该插件仅通过加载字体触发 AWT/Swing 内部结构(精确:SunFontManager
)。 SunFontManager
依次添加关闭 Hook 以在 JVM 退出时执行一些内部处理。我不想否认插件加载字体(因为它必须加载),我不想否认 Java 内部添加他们的东西。
对我来说,我似乎必须授予代码更多权限(如果 sun.*|java.*|javax.*
包在堆栈跟踪中..uuuhmm.. .ugly) 比正常情况下。但这打破了安全框架的约定,该约定假定客户端代码不能拥有比调用它的代码更多的特权。
我如何区分不是插件代码而是 Java 内部想要做某事?或者是否有任何其他方法可以确保不会通过否认某些东西来破坏内部结构?
为了让事情更清楚,这是我的应用程序中实际发生的事情。我安装了一个自定义的 SecurityManager,它应该拒绝插件直接执行的 addShutdownHook
,但如果作为 Java 内部类的副作用执行,则不应拒绝这些调用。
Context: Calls:----------------------------------------------AppClassloader Application |PluginClassloader PluginObject.init() |AppClassloader Font.create() | AccessController.doPrivileged(...) { Runtime.addShutdownHook(...) }
The SecurityManager was installed using System.setSecurityManager()
and does this:
@Override
public void checkPermission(java.security.Permission perm) {
if (perm.getName().equals("shutdownHooks")) {
if (threadContextClassLoaderIsPluginClassLoader()) {
throw new SecurityException("Installing shutdown hooks is not allowed.");
}
}
}
尽管 addShutdownHook
是在 doPrivileged
block 中调用的,但我的 SecurityManager
被调用了。我错过了什么吗?我应该自己检查特权上下文吗?
最佳答案
我发现我完全误解了 Java 安全概念。我想为插件代码构建一个沙箱,以便它始终在受限环境中运行,我可以控制它拥有的权限。该应用程序应始终在授予完全访问权限的情况下运行。
以下是如何为由单独的类加载器加载的类构建沙箱:
java.lang.SecurityManager
根据您可能做错的权限允许或拒绝操作!你只需要安装默认的java.lang.SecurityManager
通过这样做 System.setSecurityManager(new SecurityManager());
.现在,您可以使用 Java 默认值获得有效的访问控制。Grant all permissions to application 加载插件的应用程序应该获得完全访问权限。这是因为我们相信自己。我通过使用授予所有访问权限的策略文件启动我的应用程序来解决这个问题。我认为应用程序启动时需要策略文件,因为 AppClassLoader 需要为类创建正确的保护域。使用 JavaVM 参数启动主应用程序 java.security.policy=<URL-TO-POLICY>
其中 <URL-TO-POLICY
指向以下策略文件:
grant {
permission java.security.AllPermission;
};
自定义策略实现 我们需要在应用程序启动后安装我们的自定义策略。我们想要分离主应用程序(在授予完全访问权限的情况下运行)和插件(我们想要限制的权限)的权限。插件应在具有精选权限的沙箱中运行。为实现这一点,这里是自定义策略实现:
class SandboxPolicy extends Policy {
@Override
public PermissionCollection getPermissions(ProtectionDomain domain) {
// Decide if the plugin permissions are needed or full access can be granted using all permissions.
if (isPlugin(domain)) {
return pluginPermissions();
} else {
return applicationPermissions();
}
}
private boolean isPlugin(ProtectionDomain domain) {
// Identify the classloader of the protection domain
// The PluginClassLoader is assumed to be the one that loaded
// the plugin
return domain.getClassLoader() instanceof PluginClassLoader;
}
private PermissionCollection pluginPermissions() {
// Empty permissions = No permissions
// This is not the point to add plugin permissions
return new Permissions();
}
private PermissionCollection applicationPermissions() {
// Grant full access to the application
Permissions permissions = new Permissions();
permissions.add(new AllPermission());
return permissions;
}
}
每个类加载器的 ProtectionDomains 类加载器负责创建一个 ProtectionDomain
对于每个来源,代码都是从中加载的。保护域指定将授予代码的权限。我们必须修改类加载器添加到保护域的权限集。为此,让您的 PluginClassloader 扩展 java.security.SecureClassLoader
.然后覆盖方法 java.security.SecureClassLoader.getPermissions(CodeSource)
通过以下方式:
@Override
protected PermissionCollection getPermissions(CodeSource codeSource)
{
PermissionCollection pc;
// The SecureClassloader per default grants access to read resources from the source JAR.
// This is useful. Call super to get those permissions:
pc = super.getPermissions(codeSource);
// At this point you can extend permissions.
// For example grant read access to a file.
pc.add(new FilePermission("path\\file", "read"));
return (pc);
}
注意:看政策执行,看看我的评论// This is not the point to add plugin permissions
. AccessController
询问政策查看是否可以授予权限。如果在此处添加权限,您可以从调用者那里获得的信息非常有限。我不建议在此处计算和添加任何权限。类加载器是您可以根据代码源添加权限的地方。我建议在这里添加权限。它们在保护域中变得可见,您可以轻松观察 AccessController 使用这些保护域执行的操作。
特权操作
我想回答问题中的另一部分。
The interesting thing is, that I realized, that it is not the plugin itself that wants to add a shutdown hook. The plugin just triggers the AWT/Swing internals (precise: SunFontManager) by loading a font.
有些操作将作为插件代码的副作用执行。 A类org.plugin.A
可以触发 Swing/AWT 内部添加一个关闭钩子(Hook)。在这种情况下,我们不想否认这一点。 Java 类在应用程序的范围内,应该具有完全访问权限。插件代码可能会受到限制,直接添加关闭 Hook 应该会失败并返回 SecurityException
。 .这是 java.security.AccessController.doPrivileged(PrivilegedAction<T>)
的常见用例.特权操作确保 AccessController
只会考虑最后一个堆栈帧的保护域。 AWT/Swing 将其关闭 Hook 添加到一个特权操作中,因此被允许这样做,因为在该操作中执行的类的保护域设置为具有完全访问权限。请参阅 java.security.AccessController
的任何文档了解有关特权操作的更多信息。
关于java - 如何搭建沙箱环境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39974300/
为了构建 CentOS 6.5 OSM 切片服务器,我正在寻找一些文档和/或教程。 我试过this one正如我在我的 previous post 中所说的那样但它适用于 Ubuntu 14.04,而
我正在寻找可用于集成任何源代码控制管理系统的通用 git 桥(如 git-svn、git-p4、git-tfs)模板。 如果没有这样的模板,至少有一些关于如何在 git 端集成基本操作的说明(对于其他
1、前言 redis在我们企业级开发中是很常见的,但是单个redis不能保证我们的稳定使用,所以我们要建立一个集群。 redis有两种高可用的方案: High availabilit
简介 前提条件: 确保本机已经安装 VS Code。 确保本机已安装 SSH client, 并且确保远程主机已安装 SSH server。 VSCode 已经安装了插件 C/
为什么要用ELK ELK实际上是三个工具,Elastricsearch + Logstash + Kibana,通过ELK,用来收集日志还有进行日志分析,最后通过可视化UI进行展示。一开始业务量比
在日常办公当中,经常会需要一个共享文件夹来存放一些大家共享的资料,为了保证文件数据的安全,最佳的方式是公司内部服务器搭建FTP服务器,然后分配多个用户给相应的人员。今天给大家分享FileZilla搭
最近由于业务需要,开始进行 Flutter 的研究,由于 Flutter 的环境搭建在官网上有些细节不是很清楚,笔者重新整理输出 1. 配置镜像 由于在国内访问 Flutter
目录 1. 安装go软件包 2. 配置系统变量 3. 安装git 4. 设置go代理 5. 下载gin框架 6. 创建项目 7.
Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任
上篇文章给大家介绍了使用docker compose安装FastDfs文件服务器的实例详解 今天给大家介绍如何使用 docker compose 搭建 fastDFS文件服务器,内容详情如下所示:
目录 1.创建Maven 2.Maven目录和porm.xml配置 3.配置Tomcat服务器 1.创建Maven
laravel 官方提供 homestead 和 valet 作为本地开发环境,homestead 是一个官方预封装的 vagrant box,也就是一个虚拟机,但是跟 docker 比,它占用体积
这个tutorial显示了 Razor Pages 在 Asp.Net Core 2 中的实现。但是,当我运行 CLI 命令时: dotnet aspnet-codegenerator razorp
我创建了一个单独的类库项目来存储数据库上下文和模型类。在同一解决方案中,我创建了一个 ASP.NET MVC 项目并引用了类库项目,并在项目的 Web.config 文件中包含了数据库上下文的连接字符
关于代码托管,公司是基于Gitlab自建的,它功能全而强大,但是也比较重,我个人偏向于开源、小巧、轻便、实用,所以就排除了Github,在Gogs和Gitea中选者。Gogs在Github有38
目录 1、高可用简介 1.1 高可用整体架构 1.2 基于 QJM 的共享存储系统的数据同步机制分析 1.3 NameNode 主
Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru 站点开发的,它已经在该站点运行超过两年半了。Igor 将源代码以类BSD许可证的形式发布。 在高并发连接的情况
对于我们的 ASP.NET Core 项目,我们使用包管理器控制台中的 Scaffold-DbContext 搭建现有数据库。 每次我们做脚手架时,上下文类与所有实体一起生成,它包含调用 option
我正在使用 .net 核心 2.0。我已经安装了以下 nuget 包:1: Microsoft.AspNetCore.All2: Microsoft.EntityFrameworkCore.Tools
我正在使用 NetBeans 及其 RAD 开发功能开发 JEE6 JSF 应用程序。我想使用脚手架来节省更新 Controller 和模型 View 的时间。 OneToMany 关联在 View
我是一名优秀的程序员,十分优秀!