深入Java虚拟机(3)——安全
因为网络允许多台计算机共享数据和分布式处理,所以它提供了一条入侵计算机系统的潜在途径,使得其他人可以窃取信息,改变或破坏信息,盗取计算机资源等等。为了解决由网络引起的安全问题,Java体系结构采用了一个扩展的内置安全模型,这个模型随着Java平台的主要版本不断发展:
1.0版本的基本沙箱
1.1版本的代码签名和认证
1.2版本的细粒度访问控制
Java安全模型侧重于保护终端用户免受从网络下载的、来自不可靠来源的、恶意程序(以及善意程序中的bug)的侵犯。为此,Java从JDK 1.0开始实现了一套沙箱环境(基本沙箱),沙箱对不可靠的活动进行了限制,程序可以在沙箱的安全边界内做任何事,但不能进行任何跨越这些边界的举动。
但由于最初的沙箱限制过于严格,善意(但不可靠)的代码常常无法进行有效工作。在版本1.1中,得到了改进,引入了基于代码签名和认证的信任模式。使得接收终端系统哦就能够可以确认一系列class文件(在一个jar文件中)已经由某一实体进行了数字签名(有效,可被信赖),并且在签名过后,这些class文件没有改动,这使得终端用户和系统管理员减少了对某些代码在沙箱中的限制,但这些代码必须已由可信任团体进行数字签名。
虽然版本1.1中发布的安全API包含了对认证的支持,但是实际上,除了提供完全信任和完全不信任策略(换句话说,代码要么完全被信任,要么我完全不被信任)以外,没有提供其他实际帮助。后面的1.2版本提供的API可以帮助建立细粒度的安全策略。
下面详细看看基本沙箱、代码签名和认证、细粒度访问控制是如何实现的。
基本沙箱
Java沙箱 安全建立在 Java 运行时环境的三个基本方面的基础上:ByteCode Verifier(字节码验证器)、Security Manager(安全管理器)以及 ClassLoader(类装入器)。
ByteCode Verifier:它确保所下载的代码被恰当地格式化,字节码(“Java 虚拟机”指令)没有违反这种语言或虚拟机的安全限制(无非法数据转换),没有执行指针寻址,内部堆栈不能溢出或下溢,以及字节码指令将拥有正确的类型参数。
Security Manager:它在尝试执行文件 I/O 和网络 I/O、创建新的ClassLoader、操作线程或线程组、启动底层平台(操作系统)上的进程、终止“Java 虚拟机”、将非 Java 库(本机代码)装入到 JVM、完成某种类型的窗口系统操作以及将某种类型的类装入到 JVM 中时发起运行时访问控制。
ClassLoader:Java程序(class文件)并不是本地的可执行程序。当运行Java程序时,首先运行JVM(Java虚拟机),然后再把Java class加载到JVM里头运行,负责加载Java class的这部分就叫做Class Loader。当运行一个程序的时候,JVM启动,运行bootstrapclassloader,该ClassLoader加载java核心API(ExtClassLoader和AppClassLoader也在此时被加载),然后调用ExtClassLoader加载扩展API,最后AppClassLoader加载CLASSPATH目录下定义的Class,这就是一个程序最基本的加载流程。
代码签名和认证
Java1.1的java.security包中引入的认证策略,认证能帮助用户通过实现一个沙箱来建立多种安全策略。认证可以使用户相信由某些团体担保的class文件具有高度的可信度,并且这些class文件没有在到达Java虚拟机之前的网络传输中被改变。这样,就可以简化沙箱对被认证代码的限制,针对由不同团体签名的代码建立不同的安全限制。
要对一段代码进行担保签名,首先要生成一个公钥/私钥对。用户要公开公钥,保管私钥。之后将要签名的class文件和其他文件放在一个JAR文件中,然后用诸如SDK中的jarsigner 工具对整个JAR文件签名。这个签名工具将首先通过单项散列计算,对JAR文件产生一个散列,然后用私钥对这个散列签名,并在JAR文件的末尾加上这个签名,从而完成你对这个JAR文件的数字签名。
数字签名的散列计算中大量输入的是组成JAR文件内容的字节流,产生的是不能包含所有输入信息的少量数据。这个计算是单向的:从大到小,从输入到散列。为了加强安全性,要用私钥进行加密。因为私钥加密是一个非常费时的过程,我们只对散列进行私钥的加密。公钥/私钥对具有如下特点:在仅给出公钥的情况下时,想要产生私钥是非常困难的,而且任何用私钥加密的代码都可以用配对的公钥才能解密。因为不同的输入可能产生相同的散列,而产生相同散列的概率主要依赖于散列的大小。在实际情况下,散列主要采用64位或128位,这样的长度要想从不同的输入中产生一个相同的散列的计算是不可行的。之后将这个加密后的散列值加到同一个JAR文件中,这个JAR文件还包含了你最初产生这个散列的文件。
接受者必须用公钥对签名散列进行解密,通过得到的结果和从JAR文件计算得到的散列是否相同,可以验证一个已经签名的JAR文件。如果得到的散列值和解密的散列值匹配,则表明了接受者收到的JAR文件确实被发送者所担保,并且传输过程中没有被修改,这个文件安全性是有保障的。这样,就可以将这个JAR文件放入安全级别不很严格的一般沙箱里,这个沙箱信任发送者的签名。
细粒度访问控制
版本1.2的安全体系结构的主要目标之一就是使建立(以签名代码为基础的)细粒度的访问控制策略的过程更为简单且更少出错。版本1.2的安全体系结构中,对应于整个Java应用程序的一个访问控制策略是由抽象类java.security.Policy的一个子类的单个实例所表示的。
安全策略是一个从描述运行代码的属性集合到这段代码所拥有的权限的映射。在版本1.2的安全体系结构中,描述运行代码的属性被总称为代码来源。一个代码来源是由一个java.security.CodeSource对象表示的,这个对象中包含了一个java.net.URL,它表示代码库和代表了签名者的零个或多个证书对象的数组。证书对象是抽象类java.security.cert.Certificate的子类的一个实例,一个Certificate对象抽象表示了从一个人到一个公钥的绑定,以及另一个为这个绑定作担保的人(以前提过的证书机构)。CodeSource对象包含了一个Certificate对象的数组,因为同一段代码可以被多个团体签名(担保)。这个签名通常是从JAR文件中获得的。
权限是用抽象类java.security.Permission的一个子类的实例表示的。一个Permission对象有三个属性:类型、名字和可选的操作。
在Policy对象中,每一个CodeSource是和一个或多个Permission对象相关联的。和一个CodeSource相关联的Permission对象被封装在java.security.PermissionCollection的一个子类实例中。
参考资料:
《深入Java虚拟机 第二版》
http://www.2cto.com/Article/201210/162438.html
http://www.1k2k.net/ligongkeji/2012/0507/52776.html
深入Java虚拟机(3)——安全的更多相关文章
- 深入Java虚拟机--判断对象存活状态
程序计数器,虚拟机栈和本地方法栈 首先我们先来看下垃圾回收中不会管理到的内存区域,在Java虚拟机的运行时数据区我们可以看到,程序计数器,虚拟机栈,本地方法栈这三个地方是比较特别的.这个三个部分的特点 ...
- 【深入Java虚拟机】之四:类加载机制
类加载过程 类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载.验证.准备.解析.初始化.使用和卸载七个阶段.它们开始的顺序如下图所示: 其中类加载的过程包括了加载.验 ...
- 《深入理解Java虚拟机》类文件结构
上节学习回顾 在上一节当中,主要以自己的工作环境简单地介绍了一下自身的一些调优或者说是故障处理经验.所谓百变不离其宗,这个宗就是我们解决问题的思路了. 本节学习重点 在前面几章,我们宏观地了解了虚拟机 ...
- 《深入理解Java虚拟机》调优案例分析与实战
上节学习回顾 在上一节当中,主要学习了Sun JDK的一些命令行和可视化性能监控工具的具体使用,但性能分析的重点还是在解决问题的思路上面,没有好的思路,再好的工具也无补于事. 本节学习重点 在书本上本 ...
- 《深入理解Java虚拟机》虚拟机性能监控与故障处理工具
上节学习回顾 从课本章节划分,<垃圾收集器>和<内存分配策略>这两篇随笔同属一章节,主要是从理论+实验的手段来讲解JVM的内存处理机制.好让我们对JVM运行机制有一个良好的概念 ...
- JVM学习(1)——通过实例总结Java虚拟机的运行机制
俗话说,自己写的代码,6个月后也是别人的代码……复习!复习!复习!涉及到的知识点总结如下: JVM的历史 JVM的运行流程简介 JVM的组成(基于 Java 7) JVM调优参数:-Xmx和-Xms ...
- Elasticsearch Java 虚拟机配置详解
Elasticsearch对Java虚拟机进行了预先的配置.通常情况下,因为这些配置的选择还是很谨慎的,所以你不需要太关心,并且你能立刻使用ElasticSearch. 但是,当你监视ElasticS ...
- 如何写出让java虚拟机发生内存溢出异常OutOfMemoryError的代码
程序小白在写代码的过程中,经常会不经意间写出发生内存溢出异常的代码.很多时候这类异常如何产生的都傻傻弄不清楚,如果能故意写出让jvm发生内存溢出的代码,有时候看来也并非一件容易的事.最近通过学习< ...
- Java虚拟机(JVM)以及跨平台原理详细的介绍
相信大家已经了解到Java具有跨平台的特性,可以"一次编译,到处运行",在Windows下编写的程序,无需任何修改就可以在Linux下运行,这是C和C++很难做到的.那么,跨平台是 ...
- Java虚拟机浅探
简介 对于java开发人员了来说,对java虚拟机肯定有着或多或少的了解.因为有了虚拟机的存在,才会使得java的内存管理变得那么方便,不再像C++那样使用new/delete来直接管理内存.知名的j ...
随机推荐
- CLR-基元类型以及溢出检查
=========(CLR via C#阅读笔记)======== 基元类型(primitive type): 基元类型也不做过多的解释,举个例子即可清晰的辨别 在java里曾使用过Sting s=& ...
- 【转】Impala导出查询结果到文件
[转载出处]http://blog.csdn.net/jobschen/article/details/68942574 想用impala-shell 命令行中将查询的结果导出到本地文件,想当然的以为 ...
- C#生成MD5码
/// <summary> /// 获取文件的MD5码 /// </summary> /// <param name="fileName">传入 ...
- JS实现数组去重方法总结(六种方法)
方法一: 双层循环,外层循环元素,内层循环时比较值 如果有相同的值则跳过,不相同则push进数组 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 Array. ...
- [LeetCode] Sentence Similarity 句子相似度
Given two sentences words1, words2 (each represented as an array of strings), and a list of similar ...
- [LeetCode] Permutation in String 字符串中的全排列
Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. I ...
- [POJ 3487]The Stable Marriage Problem
Description The stable marriage problem consists of matching members of two different sets according ...
- luogu2252 取石子游戏
题目描述 有两堆石子,数量任意,可以不同.游戏开始由两个人轮流取石子.游戏规定,每次有两种不同的取法,一是可以在任意的一堆中取走任意多的石子:二是可以在两堆中同时取走相同数量的石子.最后把石子全部取完 ...
- 【USACO】 洞穴奶牛
题目描述 贝西喜欢去洞穴探险.这次她去的地方由 N 个洞穴组成,编号分别是 1 到 N,1 号洞穴是出发 的起点. 洞穴之间由 M 条隧道相连,双向通行,第 i 条隧道连接 A i 和 B i .每条 ...
- hdu 4578 线段树(标记处理)
Transformation Time Limit: 15000/8000 MS (Java/Others) Memory Limit: 65535/65536 K (Java/Others) ...