《Java虚拟机学习笔记》- 第三章 安全

1.     第三章 安全

Java在一开始的时候,侧重于互联网的应用,即appletapplet是一段JAVA程序,这个程序运行在浏览器中,它来源于网络。为了避免这些来源于其它地方的代码不对本地机器造成伤害,JAVA提供了基本沙箱来运行这些程序。沙箱保证了applet不能执行下面的操作:

读写硬盘

开启到宿主机的socket链接

创建新的进程

装载新的动态链接库

 

1.1  1.0版本的基本沙箱

 

组成沙箱的基本组件:

l           类装载器结构

l           Class文件检验器

l           内置于JAVA虚拟机(及语言)的安全特性

l           安全管理器及JAVA API

 

1.2  类装载器体系结构

类装载器在三个方面保证JAVA代码的安全

l           一是防止恶意代码去干涉善意代码

n         不同的类装载器装入的类都具有不同的命名空间

n         同一个类装载器中不能多次装入同一个类

n         同一个类可以被不同的类装载器装入(那么它们将具有不同的命名空间)

n         在不同命名空间中的类互相不能访问

l           二是它守护了被信任的类库边界

n         这主要通过不同的类加载器来加载可靠的和不可靠的代码来实现

n         双亲委派模式:一个类装载器转载一个类的时候,首先委托双亲来装载,如果双亲无法装载,则委托双亲的双亲来装载,直到启动类装载器;如果这些装载器都无法装载,则由这个类装载器自己来装载

n         比如我们运行一个自己写的JAVA程序,那么在程序启动之前,JAVA虚拟机将创建三个类装载器:启动类装载器和扩展类装载器和系统类装载器,启动类装载器负责装载JDK核心类库中的类,扩展类装载器负责装载扩展目录中的类,而系统装载器负责装载类路径中的类。

 

加载的时候,一路往上委托,从启动类加载器尝试加载,如果不行,再由扩展类装载器来装载,如果还不行,则由系统(类路径)类装载器来装载,如果还不行,则由网络类装载器来装载。

 

这种委派模式防止了其它类伪装标准JDK类库中的类。比如,网络类装载器如果试图装载一个java.lang.Integer类,因为这个类是JDK核心类库中的类,所以它将由启动类装载器装载,避免了伪装的发生。

 

还有一种情况,比如假设我们现在编写一个java.lang.Virus(病毒)类,伪装是java.lang这个包的一个类,如果伪装成功,它将得到java.lang这个包的包访问权限。现在这个类,确实是由网络类加载器来加载了,但是它将得不到核心类库中java.lang这个包的包访问权限,因为这个类和其它在java.lang这个包中的类不属于同一个类装载器。也就是说在编译阶段,虽然java.lang.Virusjava.lang.Integer等是属于同一个包的,但是在运行的时候,它们是由不同的类装载器的,这称为运行时包,即它们不属于同一个运行时包。对于这样的类,它将得不到任何特殊的访问权限。

 

刚才讲到不同类装载器装载的类不能互相访问,那么具有父子关系的类装载器呢?这些应该是可以互相访问的?

 

答:子女装载器可以看到父母装载器装载的类,但父母装载器装载的类将看不到子女装载器装载的类。

 

l           三是它将代码归入某类(称保护域),该类确定了代码可以进行哪些操作

n         类装载器将装载的类放到一个保护域中,一个保护域定义了它将得到怎样的权限

 

1.3  Class文件检验器

Class文件就是一个字节码序列,在装载的时候,需要对class文件进行检验,以便它符合规范(而不是一个由黑客创建的类)。Class文件检验器在执行前,对class进行校验。分为四趟独立的扫描来完成检验:

l           第一趟:class文件的结构检查

n         这个主要确保它是一个class文件,而不是别的文件(比如.exe/.txt/.jpg等文件)以及文件是否有删节等等

l           第二趟:类型数据的语义检查

n         将检查比如一个方法描述符是否合法、除Object类以外的其它所有类是否都有一个超类、final类没有被子类化、final方法没有被覆盖等等

n         实际上就是检查这个类是否符合在编译时必需遵守的强制规则

l           第三趟:字节码验证

n         首先理解字节码流:操作码指令+操作数,这样的序列,就是字节码流。

n         执行线程,就等于逐个执行操作码指令

n         每个线程,被授予其自己的JAVA栈,这个栈由不同的栈帧(一个内存片段)构成

n         每一次方法调用,都会获得一个自己的栈帧,栈帧用来存放局部变量和计算的中间结果(所谓中间结果,比如:int i = a + b + c + d,那么首先执行a+b,其结果就是中间结果,把这个中间结果再加上c,得到另外一个中间结果,然后再加上d,最后得到结果i

n         在栈帧中,用于存储方法的中间结果的部分称为该方法的操作数栈

n         在执行一个操作码指令时,除了可以使用直接紧跟其后的操作数之外,还可以使用操作数栈中的数据,或局部变量中的数据

n         字节码验证就是验证操作码指令和操作数的合法性等等

l           第四趟:符号引用的验证

n         在动态链接过程中,包含在一个类中的符号引用被解释时,将进行第四趟验证。

n         一个类可能包含了对其它类的符号引用,一个符号引用就是一个字符串,它给出了这个引用的相关信息。包括对类的引用,对字段的引用,对方法的引用。如果是对类的引用,需给出类的全名;如果是对字段的引用,需给出类名、字段名和字段描述符;如果是对方法的引用,需给出类名、方法名、以及方法的描述符

n         这一般在代码运行到需要加载其它类的时候才会去执行这第四趟验证(即延迟验证了)

n         所谓动态链接:即将符号引用解析为直接引用的过程。

u        查找被引用的类(有必要的话就加载它)

u        将符号引用替换为直接引用,例如一个指向类、字段或方法的指针

1.4  Java虚拟机中内置的安全特性

l           类型安全的类型转换

l           结构化的内存访问(无指针算法)

l           自动垃圾收集

l           数组边界检查

l           空引用检查

 

1.5  安全管理器和JAVA API

前三个特性主要是避免JAVA虚拟机和应用程序受到外来代码的破坏。安全管理器,则是为了避免在虚拟机中运行的程序恶意访问外部资源。

 

安全管理器就是用来控制对外部资源的访问的。

 

在启动java程序的时候,如果没有设置安全管理器,则将不使用安全管理器。所以所有API都可以使用。

 

安全管理器负责两个方面的工作:定义安全策略、执行安全策略

 

JAVA1.2版本开始,已经提供了缺省的安全管理器实现,因此,我们只需要编写一个策略文件即可(文本文件)。

 

1.6  代码签名和认证

java.security及其子包。

认证可以使得用户确认,由某些团体担保的.class代码是值得信任的,并且这些class文件在到达虚拟机之前没有被改动过。如果用户信任这个团体,则可以减少沙箱对代码所实施的限制!可以对由不同团体签名的代码建立不同的安全限制。

 

在继续往下之前,你需要了解关于加解密的基础知识:对称加密算法、非对称加密算法、不可逆加密算法。不可逆加密算法的目的是防篡改,即从一个文档的数据流中生成一段散列值(64位或128位)。一般情况下,不同的文档生成的散列值不同(相同的概率非常小),所以,可以认为这段散列值就代表了这个文档,一旦文档被篡改,则散列值就不同了!所以,只要把散列值和文档一起传输,接收方对接收到的文档再次计算其散列值,判断这个散列值和接收到的散列值是否一致,就可以判定这个文档是否经过了篡改!

 

看起来想法不错,但是这里面存在的问题就是,散列值在传输过程中也可能被更改,所以,必需对其加密(只对散列值进行加密,速度比较快),采用非对称加密技术来对散列值加密。

非对称加密技术有两个密钥:公钥和私钥,如果使用私钥加密,则必须使用公钥解密;如果使用公钥加密,则必须使用私钥解密。如果要对一个jar包的散列值进行加密,一般就用私钥加密,然后公布公钥,对方使用公钥来解密。

 

 

 

随之带来的问题就是,如何把我的公钥公布给对方?因此引入第三方可信任的证书机构来提供证书服务。即我可以把公钥提交给证书机构,由证书机构来对我的公钥用它的私钥进行加密,最终得到的就是证书!jar文件的接收者可以使用证书机构的公钥来解密证书,从而得到真正的公钥,再用这个公钥去解密散列即可。

 

 

1.7  策略

定义策略文件,以便控制appletJAVA应用程序对资源的访问权限(比如文件、socket等),

策略文件示例:

 

1.8  保护域

 

当类装载器将类装入JAVA虚拟机时,将给每个类型指派一个保护域。每个类型只能属于一个保护域(一个保护域对应策略文件中的一个或多个grant子句)。

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值