什么是沙箱^1

Java安全模型的核心就是Java沙箱(sandbox),什么是沙箱?沙箱是一个限制程序运行的环境。限制程序运行一方面是为了保护系统资源,同时另一方面也为了保护程序自己。沙箱主要限制系统资源访问,那系统资源包括什么?——CPU、内存、文件系统、网络。不同级别的沙箱对这些资源访问的限制也可以不一样。

所有的Java程序运行都可以指定沙箱,可以定制安全策略。而一个Java程序运行的安全策略,包括了以下几点基础:字节码校验器(bytecode verifier):确保Java类文件遵循Java语言规范。这样可以帮助Java程序实现内存保护。但是不是所有的类文件都会经过字节码校验,比如核心类。

类加载器(class loader):所有的Java类都是通过类加载器加载的,可以自定义类加载器来设置加载类的权限。

存取控制器(access controller):存取控制器可以控制核心API对操作系统的存取权限,而这个控制的策略设定,可以由用户指定。

安全管理器(security manager):是核心API和操作系统之间的主要接口。实现权限控制,比存取控制器优先级高。

安全软件包(security package):java.security下的类和扩展包下的类,允许用户为自己的应用增加新的安全特性,包括:安全提供者

消息摘要

数字签名

加密

鉴别

沙箱包含哪些要素

1. 权限

权限是指允许代码执行的操作。包含三部分:权限类型、权限名和允许的操作。权限类型是实现了权限的Java类名,是必需的。权限名一般就是对哪类资源进行操作的资源定位(比如一个文件名或者通配符、网络主机等),一般基于权限类型来设置,有的比如java.security.AllPermission不需要权限名。允许的操作也和权限类型对应,指定了对目标可以执行的操作行为,比如读、写等。如下面的例子:permission java.security.AllPermission; //权限类型

permission java.lang.RuntimePermission "stopThread"; //权限类型+权限名

permission java.io.FilePermission "/tmp/foo" "read"; //权限类型+权限名+允许的操作

标准权限有哪些类型权限名操作例子文件权限java.io.FilePermission文件名(平台依赖)读、写、删除、执行允许所有问价的读写删除执行:permission java.io.FilePermission "<< ALL FILES>>", "read,write,delete,execute";。允许对用户主目录的读:permission java.io.FilePermission "${user.home}/-", "read";。

套接字权限java.net.SocketPermission主机名:端口接收、监听、连接、解析允许实现所有套接字操作:permission java.net.SocketPermission "*:1-", "accept,listen,connect,resolve";。允许建立到特定网站的连接:permission java.net.SocketPermission "*.abc.com:1-", "connect,resolve";。

属性权限java.util.PropertyPermission需要访问的jvm属性名读、写读标准Java属性:permission java.util.PropertyPermission "java.*", "read";。在sdo包中创建属性:permission java.util.PropertyPermission "sdo.*", "read,write";。

运行时权限java.lang.RuntimePermission多种权限名[见附录A]无允许代码初始化打印任务:permission java.lang.RuntimePermission "queuePrintJob"

AWT权限java.awt.AWTPermission6种权限名[见附录B]无允许代码充分使用robot类:permission java.awt.AWTPermission "createRobot"; permission java.awt.AWTPermission "readDisplayPixels";。

网络权限java.net.NetPermission3种权限名[见附录C]无允许安装流处理器:permission java.net.NetPermission "specifyStreamHandler";。

安全权限java.security.SecurityPermission多种权限名[见附录D]无

序列化权限java.io.SerializablePermission2种权限名[见附录E]无

反射权限java.lang.reflect.ReflectPermissionsuppressAccessChecks(允许利用反射检查任意类的私有变量)无

完全权限java.security.AllPermission无(拥有执行任何操作的权限)无

2. 代码源

代码源是类所在的位置,表示为以URL地址。

3. 保护域

保护域用来组合代码源和权限,这是沙箱的基本概念。保护域就在于声明了比如由代码A可以做权限B这样的事情。

4. 策略文件

策略文件是控制沙箱的管理要素,一个策略文件包含一个或多个保护域的项。策略文件完成了代码权限的指定任务,策略文件包括全局和用户专属两种。

为了管理沙箱,策略文件我认为是最重要的内容。JVM可以使用多个策略文件,不过一般两个最常用。一个是全局的:$JREHOME/lib/security/java.policy,作用于JVM的所有实例。另一个是用户自己的,可以存储到用户的主目录下。策略文件可以使用jdk自带的policytool工具编辑。

默认的策略文件我们先参考一下:// Standard extensions get all permissions by default

grant codeBase "file:${{java.ext.dirs}}/*" {

permission java.security.AllPermission;

};

// default permissions granted to all domains

grant {

// Allows any thread to stop itself using the java.lang.Thread.stop()

// method that takes no argument.

// Note that this permission is granted by default only to remain

// backwards compatible.

// It is strongly recommended that you either remove this permission

// from this policy file or further restrict it to code sources

// that you specify, because Thread.stop() is potentially unsafe.

// See the API specification of java.lang.Thread.stop() for more

// information.

permission java.lang.RuntimePermission "stopThread";

// allows anyone to listen on dynamic ports

permission java.net.SocketPermission "localhost:0", "listen";

// permission for standard RMI registry port

permission java.net.SocketPermission "localhost:1099", "listen";

// "standard" properies that can be read by anyone

permission java.util.PropertyPermission "java.version", "read";

permission java.util.PropertyPermission "java.vendor", "read";

permission java.util.PropertyPermission "java.vendor.url", "read";

permission java.util.PropertyPermission "java.class.version", "read";

permission java.util.PropertyPermission "os.name", "read";

permission java.util.PropertyPermission "os.version", "read";

permission java.util.PropertyPermission "os.arch", "read";

permission java.util.PropertyPermission "file.separator", "read";

permission java.util.PropertyPermission "path.separator", "read";

permission java.util.PropertyPermission "line.separator", "read";

permission java.util.PropertyPermission "java.specification.version", "read";

permission java.util.PropertyPermission "java.specification.vendor", "read";

permission java.util.PropertyPermission "java.specification.name", "read";

permission java.util.PropertyPermission "java.vm.specification.version", "read";

permission java.util.PropertyPermission "java.vm.specification.vendor", "read";

permission java.util.PropertyPermission "java.vm.specification.name", "read";

permission java.util.PropertyPermission "java.vm.version", "read";

permission java.util.PropertyPermission "java.vm.vendor", "read";

permission java.util.PropertyPermission "java.vm.name", "read";

};

策略文件的内容格式就是这样,grant授权允许操作某个权限。这个默认的策略文件就指明了jdk扩展包可以有全部权限,允许代码stop线程,允许监听1099端口等等。

另一个很重要的是参数文件——java.security,这个文件和策略文件在同一个目录下。这个参数文件定义了沙箱的一些参数。比如默认的沙箱文件是这样的(截取部分):# The default is to have a single system-wide policy file,

# and a policy file in the user's home directory.

policy.url.1=file:${java.home}/lib/security/java.policy

policy.url.2=file:${user.home}/.java.policy

# whether or not we expand properties in the policy file

# if this is set to false, properties (${...}) will not be expanded in policy

# files.

policy.expandProperties=true

# whether or not we allow an extra policy to be passed on the command line

# with -Djava.security.policy=somefile. Comment out this line to disable

# this feature.

policy.allowSystemProperty=true

policy.url.*这个属性指明了使用的策略文件,如上文所述,默认的两个位置就在这里配置,用户可以自行更改顺序和存储位置。而policy.allowSystemProperty指明是否允许用户自行通过命令行指定policy文件。

5. 密钥库

保存密钥证书的地方。

默认沙箱

通过Java命令行启动的Java应用程序,默认不启用沙箱。要想启用沙箱,启动命令需要做如下形式的变更:java -Djava.security.manager

沙箱启动后,安全管理器会使用两个默认的策略文件来确定沙箱启动参数。当然也可以通过命令指定:java -Djava.security.policy=

如果要求启动时只遵循一个策略文件,那么启动参数要加个等号,如下:java -Djava.security.policy==

如何使用

1. 限制读文件

这个例子很简单,首先写一个r.txt文件,里面的内容是“abcd”,再写个程序如下读取这个r.txt。import java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStream;

public class PolicyTest{

public static void file() {

File f = new File("D:\\github\\CDLib\\src\\main\\resources\\security\\r.txt");

InputStream is;

try {

is = new FileInputStream(f);

byte[] content = new byte[1024];

while (is.read(content) != -1) {

System.out.println(new String(content));

}

} catch (FileNotFoundException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (IOException e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public static void main(String[] args) {

// test read file.

file();

}

}

发现输出是abcd。

接下来修改java启动参数,加入-Djava.security.manager,启动了安全沙箱。再运行,输出变成了异常Exception in thread "main" java.security.AccessControlException: access denied ("java.io.FilePermission" "D:\github\CDLib\src\main\resources\security\r.txt" "read")at java.security.AccessControlContext.checkPermission(Unknown Source)at java.security.AccessController.checkPermission(Unknown Source)at java.lang.SecurityManager.checkPermission(Unknown Source)at java.lang.SecurityManager.checkRead(Unknown Source)at java.io.FileInputStream.(Unknown Source)at com.taobao.cd.security.PolicyTest.main(PolicyTest.java:15)

这里已经提示了,访问被拒绝,说明了沙箱启动,同时也验证了默认沙箱——禁止本地文件访问。

再来,我们构建一个custom.policy文件如下:grant {

permission java.io.FilePermission "D:\\github\\CDLib\\src\\main\\resources\\security\\*", "read";

};

这里构建了一条安全策略——允许读取security目录下的文件。

修改启动命令,添加-Djava.security.policy=D:\\github\\CDLib\\src\\main\\resources\\security\\custom.policy,再执行,结果输出了abcd。

如上例。我们通过自定义policy文件修改了默认沙箱的安全策略,再通过启动参数开启沙箱模式。这样就可以构造我们自己想要的沙箱效果了。

2. 限制访问网络

通过HttpClient访问www.baidu.comimport java.io.File;

import java.io.FileInputStream;

import java.io.FileNotFoundException;

import java.io.IOException;

import java.io.InputStream;

import com.taobao.cd.http.util.HttpUtil;

public class PolicyTest{

public static void network() {

try {

String text = HttpUtil.createHtmlText("http://www.baidu.com", HttpUtil.UA);

System.out.println(text);

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

public static void main(String[] args) {

// test use network.

network();

}

}

开启默认沙箱后,输出如下:java.security.AccessControlException: access denied ("java.net.SocketPermission" "www.baidu.com" "resolve")at java.security.AccessControlContext.checkPermission(Unknown Source)at java.security.AccessController.checkPermission(Unknown Source)at java.lang.SecurityManager.checkPermission(Unknown Source)at java.lang.SecurityManager.checkConnect(Unknown Source)at java.net.InetAddress.getAllByName0(Unknown Source)at java.net.InetAddress.getAllByName(Unknown Source)at java.net.InetAddress.getAllByName(Unknown Source)at org.apache.http.impl.conn.DefaultClientConnectionOperator.resolveHostname(DefaultClientConnectionOperator.java:242)at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:130)at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:149)at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:121)at org.apache.http.impl.client.DefaultRequestDirector.tryConnect(DefaultRequestDirector.java:573)at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:425)at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:820)at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:754)at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:732)at com.taobao.cd.http.util.HttpUtil.createHtmlText(HttpUtil.java:38)at com.taobao.cd.security.PolicyTest.network(PolicyTest.java:15)at com.taobao.cd.security.PolicyTest.main(PolicyTest.java:45)

根据错误提示,知道是访问socket没有权限。那么修改下policy,指定权限:grant {

permission java.net.SocketPermission "www.baidu.com:1-", "connect,resolve";

};

在指定权限文件下再运行,得到了正常的text形式的baidu首页的页面文档。权限策略成功。

附录

A权限名用途说明accessClassInPackage.允许代码访问指定包中的类

accessDeclaredMembers允许代码使用反射访问其他类中私有或保护的成员

createClassLoader允许代码实例化类加载器

createSecurityManager允许代码实例化安全管理器,它将允许程序化的实现对沙箱的控制

defineClassInPackage.允许代码在指定包中定义类

exitVM允许代码关闭整个虚拟机

getClassLoader允许代码访问类加载器以获得某个特定的类

getProtectionDomain允许代码访问保护域对象以获得某个特定类

loadlibrary.允许代码装载指定类库

modifyThread允许代码调整指定的线程参数

modifyThreadGroup允许代码调整指定的线程组参数

queuePrintJob允许代码初始化一个打印任务

readFileDescriptor允许代码读文件描述符(相应的文件是由其他保护域中的代码打开的)

setContextClassLoader允许代码为某线程设置上下文类加载器

setFactory允许代码创建套接字工厂

setIO允许代码重定向System.in、System.out或System.err输入输出流

setSecurityManager允许代码设置安全管理器

stopThread允许代码调用线程类的stop()方法

writeFileDescriptor允许代码写文件描述符

B权限名用途说明accessClipboard允许访问系统的全局剪贴板

accessEventQueue允许直接访问事件队列

createRobot允许代码创建AWT的Robot类

listenToAllAWTEvents允许代码直接监听事件分发

readDisplayPixels允许AWT Robot读显示屏上的像素

showWindowWithoutWarningBanner允许创建无标题栏的窗口

C权限名用途说明specifyStreamHandler允许在URL类中安装新的流处理器

setDefaultAuthenticator可以安装鉴别类

requestPassworkAuthentication可以完成鉴别

D权限名用途说明addIdentityCertificate为Identity增加一个证书

clearProviderProperties.针对指定的提供者,删除所有属性

createAccessControlContext允许创建一个存取控制器的上下文环境

getDomainCombiner允许撤销保护域

getPolicy检索可以实现沙箱策略的类

getProperty.读取指定的安全属性

getSignerPrivateKey由Signer对象获取私有密钥

insertProvider.将指定的提供者添加到响应的安全提供者组中

loadProviderProperties.装载指定的提供者的属性

printIdentity打印Identity类内容

putAllProviderProperties.更新指定的提供者的属性

putProviderProperty.为指定的提供者增加一个属性

removeIdentityCertificate取消Identity对象的证书

removeProvider.将指定的提供者从相应的安全提供者组中删除

removeProviderProperty.删除指定的安全提供者的某个属性

setIdentityInfo为某个Identity对象设置信息串

setIdentityPublicKey为某个Identity对象设置公钥

setPolicy设置可以实现沙箱策略的类

setProperty.设置指定的安全属性

setSignerKeyPair在Signer对象中设置密钥对

setSystemScope设置系统所用的IdentityScope

E权限名用途说明enableSubstitution允许实现ObjectInputStream类的enableResolveObject()方法和ObjectOutputStream类的enableReplaceObject()方法

enableSubclassImplementation允许ObjectInputStream和ObjectOutputStream创建子类,子类可以覆盖readObject()和writeObject()方法

java平台沙箱安全组件_java Security--java沙箱相关推荐

  1. java 画笔跟swing组件_Java学习教程(基础)--Java版本历史(二)

    Java语言自JDK1.0版本以来经历了许多次更新,也在基本程序库中增加了大量的类别和包.从J2SE 1.4开始,Java语言的变动由 Java Community Process(JCP)管理,JC ...

  2. java 画笔跟swing组件_java组件及事件处理(简单基础的界面操作)1

    尽管Java的优势是网络应用方面,但Java也提供了强大的用于开发桌面程序的API,这些API在javax.swing包中,对此,本文章将先介绍一部分Java界面处理的简单操作. 1.Java Swi ...

  3. java 平台级模块系统_Java平台模块系统公众审查未能通过

    java 平台级模块系统 在过去的几周里,Java世界中的戏剧,阴谋和政治活动异常高涨,最终在本周的JSR 376 Java平台模块系统公共评审投票中达到了顶峰. Java模块化(包括Java平台模块 ...

  4. java取消 验证_使用Spring Security Java配置时禁用基本身份验证

    我正在尝试使用Spring Security Java配置保护Web应用程序的安全. 这是配置的样子: @Configuration @EnableWebMvcSecurity public clas ...

  5. java简易计算器实验报告_Java 《Java 实现简单计算器》实验报告

    15325592-d9e8874662abf194.png 环境 macOS java 15 Eclipse 创建项目 项目命名 2020-10-19_5f8d56908a700.png 如上图所示, ...

  6. java设计工资一般多少_java开发(java开发工程师工资一般多少)

    java开发 Java,是于1995年5月被推出的Java程序设计言语和Java平台的总称.[1]Java起源于Oak,是由JamesGosling等几位工程师于1995年5月推出的一种能够编写跨平台 ...

  7. java中复选框组件_Java Swing JCheckBox:复选框组件

    一个复选框有选中和未选中两种状态,并且可以同时选定多个复选框.Swing中使用 JCheckBox 类实现复选框,该类的常用构造方法如下.JCheckBox():创建一个默认的复选框,在默认情况下既未 ...

  8. java 数据透视表 组件_Java创建Excel数据透视表

    正版现货excel效率手册早做完不锡 22.82元 包邮 (需用券) 去购买 > Excel 数据透视表具有强大的数据处理功能,能够使表格中的数据更加直观化.使用Excel 数据透视表,能方便用 ...

  9. java 数据透视表 组件_Java在Excel中创建透视表方法解析

    本文内容介绍通过Java程序在Excel表格中根据数据来创建透视表. 环境准备 需要使用Excel类库工具-Free Spire.XLS for Java,这里使用的是免费版,可通过官网下载Jar包并 ...

最新文章

  1. 【Qt】Qt5在ubuntu16.04无法输入中文解决方式
  2. 计算两个日期之间的工作日
  3. docker mysql 报错 “Too many connections 1040“ 修改最大连接数 未生效 解决方法
  4. Linux 环境下的高级隐藏技术
  5. spring cloud config动态刷新_SpringCloud-Config
  6. PHP函数之CURL: 常见问题总结
  7. 解释内存中的栈、堆、静态区
  8. linux java version 版本不对,linux JAVA_HOME和 java -version不匹配
  9. 201771010126 王燕《面向对象设计 java》第十五周实验总结
  10. NUC1313 皇帝的金币
  11. linux命令别名永久生效
  12. proj编译linux,在Ubuntu上安装proj 投影转换程序
  13. Operations Manager 2007 R2 Beta可下载试用
  14. 4月28日上午学习日志
  15. 空间数据分析与R语言实践
  16. IEEE极限编程:Word Ordering
  17. 开心网倒闭变卖,创始人程炳皓反思的亲笔信全文
  18. 安装deepin后没有Windows启动项解决办法
  19. 微信自定义分享功能实现
  20. SAP MM批次管理(4)批次分类

热门文章

  1. KDZD程控超低频高压发生器
  2. 2020计算机统考题,2020年7月网络教育统考计算机应用基础模拟题试卷9
  3. The Farthest Distance in the World (Tagore)
  4. Video Understanding(视频理解,I3D,SlowFast,Non-local)
  5. Java基于j2ee+mysql的花鸟鱼虫花卉市场管理系统
  6. Scala往List中添加元素
  7. centos7 默认中文字体_Linux CentOS 7 安装字体库 中文字体
  8. ajax获取显示list数据
  9. 编译器32位和64位数据类型区别
  10. 阿里P8亲自讲解!5年经验Android程序员面试27天,附答案