background image

 
bad[7] = 50;
  这段代码总是抛出一个 java.lang.ArrayOutOfBoundsException 异常,而该异常可以由
程序自行捕获:
  try {
  char[] bad = new char[6];
  bad[7] = 50;
  }
  catch (ArrayOutOfBoundsException ex) {
  ... }

  这种处理过程永远不会导致不可预料的行为。无论用什么方法溢出一个数组,我们总
是得到 ArrayOutOfBoundsException 异常,而 Java 运行时底层环境却能够保护自身免受任
何 侵 害 。 一 般 而 言 , 用 Java 字 符 串 类 型 处 理 字 符 串 时 , 我 们 无 需 担 心 字 符 串 的
ArrayOutOfBoundsExceptions 异常,因此它是一种较为理想的选择。Java 编程模式从根本
上改变了用户输入的处理方法,避免了输入缓存溢出,从而使得 Java 程序员摆脱了最危
险的编程漏洞。
  三、竞争状态
  竞争状态即 Race Condition,它是第二类最常见的应用安全漏洞。在创建(更改)资源到
修改资源以禁止对资源访问的临界时刻,如果某个进程被允许访问资源,此时就会出现
竞争状态。这里的关键问题在于:如果一个任务由两个必不可少的步骤构成,不管你多么
想要让这两个步骤一个紧接着另一个执行,操作系统并不保证这一点。例如,在数据库中,

事务机制使得两个独立的事件 原子化 。换言之,一个进程创建文件,然后把这个文件的
权限改成禁止常规访问;此同时,另外一个没有特权的进程可以处理该文件,欺骗有特权
的进程错误地修改文件,或者在权限设置完毕之后仍继续对原文件进行访问。
  一般地,在标准 Unix 和 NT 环境下,一些高优先级的进程能够把自己插入到任务的
多个步骤之间,但这样的进程在 Java 服务器上是不存在的;同时,用纯 Java 编写的程序也
不可能修改文件的许可权限。因此,大多数由文件访问导致的竞争状态在 Java 中不会出现,
但这并不意味着 Java 完全地摆脱了这个问题,只不过是问题转到了虚拟机上。我们来看看
其他各种开发平台如何处理这个问题。在 Unix 中,我们必须确保默认文件创建模式是安

全的,比如在服务器启动之前执行 umask 200”这个命令。有关 umask 的更多信息,请在
Unix

系统的命令行上执行 man umask”查看 umask 的 man 文档。在 NT 环境中,我们必须

操作 ACL(访问控制表,Access Control List)的安全标记,保护要在它下面创建文件的目录。
NT 的新文件一般从它的父目录继承访问许可。请参见
  NT 文档了解更多信息。
  Java 中的竞争状态大多数时候出现在临界代码区。例如,在用户登录过程中,系统要
生成一个唯一的数字作为用户会话的标识符。为此,系统先产生一个随机数字,然后在散
列表之类的数据结构中检查这个数字是否已经被其他用户使用。如果这个数字没有被其他
用户使用,则把它放入散列表以防止其他用户使用。代码如 Listing 1 所示:
  (Listing 1)
  // 保存已登录用户的 ID

  Hashtable hash;