Java安全——语言本身的设计

Java 安全

内在安全机制

Java语言本身的安全机制是要保护内存资源——保证内存完整性,核心的安全特性要确保程序不能非法解析或修改驻留在内存中的机密信息。从语言本身的设计角度考虑,就是要设计一组规则,在所构建的运行环境中,程序对象对内存的操作是经过定义的而不是任意的。

Java的强制约束必须严格遵循访问方法的要求。必须依照程序员制定的访问级别进行相关方法的操作。如果不遵守则会产生异常。

不能访问任意的内存地址。 Java没有指针的概念,因此不会像C++一样拿到一个指针强制转换成内存指针,再利用查找内存的方法得到本不该被获取的信息。

不能对final实体再做改动。

变量在初始化前不能使用。如果能读取未初始化的变量,就等同于可以读取任意内存地址。可以通过声明一个大的对象而盗取主机内存中的信息。

对于所有数组访问进行越界检查。越界检查除了可以减少程序错误意外,另一大贡献就是安全保障。如果整数数组后紧接着存放一个字符数组,那么通过整数数组的越界写,可以改变字符数组的内容。

对象不能任意强制转换为其他类型的对象。这种类型转换的限制不仅在编译器层面,在JVM里也做了强限制,在绕过编译器的转换(比如把被转换的对象标记为Object),JVM在运行时检查也会抛出ClassCastException。

Java语言通过上面几条约束,从语言层面保护了内存,不会允许程序在没有获得正确的访问权限时读取到本不该访问的内存。

序列化怎么保障安全

这个题目不太好,因为序列化无法保证安全。Java允许通过实现java.io.Serializable接口来使内存对象序列化为一组字节码。这组字节码通过网络或者文件等方式被其他地方的代码读取并重建一个相同结构和内容的内存对象。这是Java的序列化和反序列化过程。作为一组字节码存储在磁盘文件或者数据流里,原则上是允许被修改的。那说白了,序列化无法保障安全。但是考虑到Java语言要设计支持一组规则,至于序列化的安全,就交给使用者自己保障。

序列化的安全设计规则:

1. 可序列化的对象必须实现java.io.Serializable接口,这相当于给用户打预防针,告知其要考虑这个对象的安全问题。

2. 序列化对象声明transient变量,那么该变量不被序列化。这相当于提供了保护数据的机制。

单单从这两个层面看,已经是Java语言能做到的最大化问题了。再多,则影响到了序列化本身要实现的功能。那么具体怎么做呢?就像我们常规传输数据一样——加密,你可以选择对要序列化的变量和属性加密,在反序列化时解密来增强安全。

安全规则实施

当然这里讲到的实施其实不仅仅针对安全,但是这些实施阶段确实增强了安全性。换个角度,我们其实是看Java程序的运行过程如何对应这些语言设计规则。

编译

编译阶段,可以避免“约束”中提到的前4条规则。数组越界是运行时问题,而类型转换,在编译阶段只能做到无关类型的转换,比如下例:

staticclassFoo{

intx;

}

staticclassBar{

intx;

}

publicstaticvoidmain(String[]args){

Foofoo=newFoo();

Barbar=(Bar)foo;

}

这时编译器会提示“Cannot cast from Foo to Bar”。但是如果稍作修改,将Foo替换为Object,则编译器无能为力。

staticclassFoo{

intx;

}

staticclassBar{

intx;

}

publicstaticvoidmain(String[]args){

Objectfoo=newFoo();

Barbar=(Bar)foo;

}

链接

我们都知道,编译只是做Class文件,JVM的介入是要从load class开始的。而加载完class文件后的第一件事就是链接。链接包括验证、准备和解析这几个步骤,而验证阶段,就是安全规则介入的一个阶段。验证阶段就引入了JVM的字节码校验器。

这个阶段主要是来防御恶意编译器的攻击,或者是一些无意的程序错误。比如一个类FooBar设计如下:

publicclassFooBar{

publicStringval="abcd";

}

类FooBarTest引用了这个类并更改了val变量:

publicclassFooBarTest{

publicstaticvoidmain(String[]args){

FooBarfoobar=newFooBar();

foobar.val="abcde";

System.out.println(foobar.val);

}

}

这时我们编译并运行FooBarTest,会打印abcde。而现在如果去修复FooBar,将public改为private,然后只编译FooBar,则不会发生错误。然而本来这时也编译FooBarTest会导致编译错的。但是因为疏忽导致没有这么做,那么如果没有链接校验,FooBarTest就是错误的执行了。然而因为字节码校验器的存在,运行FooBarTest会抛出

Exceptioninthread"main"java.lang.IllegalAccessError:tried to access fieldFooBar.valfromclassFooBarTest

atFooBarTest.main(FooBarTest.java:5)

优雅的解决了这个问题。

字节码校验器通过两部分来实现这种校验。首先,其作为一个微型的定理证明机,会证明class满足下列条件(只做检查):

1. 类文件格式正确;

2. 不会基于final派生子类,也不会覆盖final方法;

3. 只有一个父类;

4. 没有对primitive类型数据进行非法转型(int->Object);

5. 对象之间没有进行类型转换;

6. 操作数栈不会出现溢出。

接下来,在代码真正执行前进行校验(称为延迟校验)。比如刚才举例中提到的异常,就是校验器在校验字段的访问合法性时抛出的。

运行

上面两个阶段检查不了的规则,放到运行时检查:数组越界和类型转换。运行时抛出ArrayIndexOutOfBoundException和ClassCastException。

结语

Java语言层面的安全设计,本身也可以看出设计思路是弥补原有C和C++的部分短板而设计的。主要目标还是防止非法内存访问。但是加入了这些限制也带来了性能的缺失,这本身就是一个trade off。

Java运行作业控制语言_Java安全——语言本身的设计相关推荐

  1. 手机JAVA运行环境下载_Java运行环境包

    Java运行环境包是一款用于帮助Java程序搭建运行环境的软件.Java语言是一个运用性极强的语言,它为我们提供了高度的安全性和跨平台的特性,许多软件程序都是由Java语言所开发,但是如果您的电脑上没 ...

  2. java 运行时 下载_Java Runtime Environment_Java运行环境8.0下载(暂未上线)_预约_飞翔下载...

    JavaRuntimeEnvironment(JRE)是可以在其上运行.测试和传输应用程序的Java平台.它包括Java虚拟机.Java核心类库和支持文件.它不包含开发工具--编译器.调试器和其它工具 ...

  3. java运行环境简称_Java程序的运行环境简称之为

    [多选题]下列选项中,应确认为企业资产的有: [简答题]任务32:开关电源PCB 设计.docx [判断题]下列源文件可保存成dog.java public class Dog { public vo ...

  4. java 运行时类型_Java基础之RTTI 运行时类型识别

    运行时类型识别(RTTI, Run-Time Type Identification)是Java中非常有用的机制,在Java运行时,RTTI维护类的相关信息. 多态(polymorphism)是基于R ...

  5. Java编程作业体会_Java作业的几点总结感想

    本次博客主要是总结近几次作业,交流一下自己的感受. 本次作业主要是对近几次Java课程的巩固作业,第一次作业主要是一些基础的题目,包括选择循环等一些基本语句,其目的在于掌握java一些基本知识,感受出 ...

  6. java运行 mavenzip包_JAVA开发必知工具-Maven-Maven生成可以直接运行的jar包的多种方式...

    大家都知道一个java应用项目可以打包成一个jar,当然你必须指定一个拥有main函数的main class作为你这个jar包的程序入口. 具体的方法是修改jar包内目录META-INF下的MANIF ...

  7. java 运行环境变量_java 环境变量配置与第一个程序运行

    从开始下载jdk,到运行出java第一个程序 ,花了5天时间 ,不过我相信万事开头难 ,以后会越来越好的 ,加油! jdk的下载: 在oracle官网上即可下载,jdk安装包,下载完以后运行安装 ,路 ...

  8. java运行class文件_java命令行下运行class文件

    今天碰到了一个很变态的问题,写了一个很简单的HelloWord.java,内容如下: package com.yanjiuyanjiu; public class HelloWorld { publi ...

  9. java 运行环境测试_java – 在多个环境中执行JUnit测试的配置

    我有一个包含JUnit测试的 Java项目,需要通过Jenkins在不同的测试环境(Dev,Staging等)上运行. 我目前在不同环境上构建项目以及将url,用户名和密码传递给测试运行器的解决方案是 ...

最新文章

  1. Angular2入门教程-1
  2. 创建springboot多模块项目
  3. spring2.5+struts2+hibernate+mysql
  4. 文献记录(part102)--Two-phase clustering process for outliers detection
  5. wait、notify、notifyAll和Condition
  6. springcloud中config和bus的使用
  7. ncurses窗口机制:newwin(),wprintw(),delwin(),box(),wborder(),
  8. /dev/mapper/centos-root 100% 虚拟机硬盘空间占满
  9. c#操作Xml(五)
  10. SVN 更新发生冲突各选项含义
  11. 代购集运系统平台一键上传淘宝商品至韩国coupang经验分享
  12. HTTP 请求 报错信息406
  13. 圣光照耀联盟—PostgreSQL临时表的创建与使用过程
  14. kafka配置SASL
  15. Word VBA中的光标操作
  16. MIT 操作系统 jos make grade出现no jos.out
  17. 台式计算机蓝牙无服务,Windows10无法找到蓝牙设置三种解决方法
  18. 运用广告监测系统,上海发布十二起违法广告典型案例-十目监测
  19. 宏碁收购Gateway 12天上演变脸大戏
  20. 常见电路分析十:万用表自动关机的原理

热门文章

  1. js 变量、函数提升
  2. VM虚拟机的配置文件(.vmx)损坏修复
  3. Flink从Kafka 0.8中读取多个Topic时的问题
  4. TortoiseSVN使用详细步骤(一)
  5. java富文本编辑器KindEditor
  6. Session分布式共享 = Session + Redis + Nginx
  7. dubbo+zookeeper坑坑坑
  8. 我的学习笔记_Windows_HOOK编程 2009-12-03 11:19
  9. hadoop 1.0.1集群安装及配置
  10. Eclipse开发struts完全指南