📄 _chapter 9.htm
字号:
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Chapter 9</title>
<link rel="stylesheet" type="text/css" href="docsafari.css">
<link rel="stylesheet" type="text/css" href="style.css">
</head>
<body>
<ul></ul>
<table width="100%" border="1" bgcolor="#EBEBFF">
<tr>
<td width="5%" align="left" valign="middle"><a href="_chapter%208.htm"><img src="Larrow.gif" width="17" height="19" border="0"></a></td>
<td align="center" valign="middle"><a class="docLink" href="Front%20matter.htm">CONTENTS</a></td>
<td width="5%" align="right" valign="middle"><a href="_chapter%2010.htm"><img src="Rarrow.gif" width="17" height="19" border="0"></a></td>
</tr>
</table>
<h2 class="docChapterTitle">Chapter 9. Security</h2>
<ul>
<li>
<p class="docList"><a class="docLink" href="#c9s1">Class Loaders</a></li>
<li>
<p class="docList"><a class="docLink" href="#c9s2">Bytecode Verification</a></li>
<li>
<p class="docList"><a class="docLink" href="#c9s3">Security Managers and Permissions</a></li>
<li>
<p class="docList"><a class="docLink" href="#c9s4">Digital Signatures</a></li>
<li>
<p class="docList"><a class="docLink" href="#c9s5">Code Signing</a></li>
<li>
<p class="docList"><a class="docLink" href="#c9s6">Encryption</a></li>
</ul>
<p class="docText">When Java technology first appeared on the scene, the
excitement was not about a well-crafted programming language but about the
possibility of safely executing applets that are delivered over the Internet
(see Chapter 10 of Volume 1 for more information about applets). Obviously,
delivering executable applets is practical only when the recipients are sure
that the code can't wreak havoc on their machines. For this reason, security was
and is a major concern of both the designers and the users of Java technology.
This means that unlike the case with other languages and systems where security
was implemented as an afterthought or a reaction to break-ins, security
mechanisms are an integral part of Java technology.</p>
<p class="docText">Three mechanisms in Java technology help ensure safety:</p>
<ul>
<li>
<p class="docList">Language design features (bounds checking on arrays, legal
type conversions only, no pointer arithmetic, and so on);</li>
<li>
<p class="docList">An access control mechanism that controls what the code can
do (such as file access, network access, and so on);</li>
<li>
<p class="docList">Code signing, whereby code authors can use standard
cryptographic algorithms to authenticate Java programming language code. Then,
the users of the code can determine exactly who created the code and whether
the code has been altered after it was signed.</li>
</ul>
<p class="docText">The Java virtual machine checks for bad pointers, invalid
array offsets, and so on. The other steps require controlling what goes to the
Java virtual machine.</p>
<p class="docText">When class files are loaded into the virtual machine, they
are checked for integrity. We show you in detail how that process works. More
importantly, we show you how to control what goes to the virtual machine by
building your own <span class="docEmphasis">class loader.</span></p>
<p class="docText">For maximum security, both the default mechanism for loading
a class and a custom class loader need to work with a <span class="docEmphasis">
security manager</span> class that controls what actions code can perform.
You'll see how to write your own security manager class.</p>
<p class="docText">Finally, you'll see the cryptographic algorithms supplied in
the <tt>java.security</tt> package, which allow for code signing and user
authentication.</p>
<p class="docText">As always, we focus on those topics that are of greatest
interest to application programmers. For an in-depth view, we recommend the book
<i>Inside Java 2 Platform Security</i> by Li Gong [Addison-Wesley 1999].</p>
<h3 class="docSection1Title" id="c9s1">Class Loaders</h3>
<p class="docText">A Java programming language compiler converts source into the
machine language of a hypothetical machine, called the <span class="docEmphasis">
virtual machine.</span> The virtual machine code is stored in a class file with
a <tt>.class</tt> extension. Class files contain the code for all the methods of
one class. These class files need to be interpreted by a program that can
translate the instruction set of the virtual machine into the machine language
of the target machine.</p>
<p class="docText">Note that the virtual machine interpreter loads only those
class files that are needed for the execution of a program. For example, suppose
program execution starts with <tt>MyProgram.class</tt>. Here are the steps that
the virtual machine carries out.</p>
<ol class="docList">
<li value="1">
<p class="docList">The virtual machine has a mechanism for loading class
files, for example, by reading the files from disk or by requesting them from
the Web; it uses this mechanism to load the contents of the <tt>MyProgram</tt>
class file.</li>
<li value="2">
<p class="docList">If the <tt>MyProgram</tt> class has instance variables or
superclasses of another class type, these class files are loaded as well. (The
process of loading all the classes that a given class depends on is called
<span class="docEmphasis">resolving</span> the class.)</li>
<li value="3">
<p class="docList">The virtual machine then executes the <tt>main</tt> method
in <tt>MyProgram</tt> (which is static, so no instance of a class needs to be
created).</li>
<li value="4">
<p class="docList">If the <tt>main</tt> method or a method that <tt>main</tt>
calls requires additional classes, these are loaded next.</li>
</ol>
<p class="docText">The class loading mechanism doesn't just use a single class
loader, however. Every Java program has at least three class loaders:</p>
<ul>
<li>
<p class="docList">The bootstrap class loader;</li>
<li>
<p class="docList">The extension class loader;</li>
<li>
<p class="docList">The system class loader (also sometimes called the
application class loader).</li>
</ul>
<p class="docText">The bootstrap class loader loads the system classes
(typically, from the JAR file <tt>rt.jar</tt>). It is an integral part of the
virtual machine, and is usually implemented in C. There is no <tt>ClassLoader</tt>
object corresponding to the bootstrap class loader. For example,</p>
<pre>String.class.getClassLoader()
</pre>
<p class="docText">returns <tt>null</tt>.</p>
<p class="docText">The extension class loader loads a standard extension from
the <tt>jre/lib/ext</tt> directory. You can drop JAR files into that directory,
and the extension class loader will find the classes in them, even without any
class path. (Some people recommend this mechanism to avoid the "class path from
hell," but see the pitfall later in this section.) The extension class loader is
implemented in Java.</p>
<p class="docText">The system class loader loads the application classes. It
locates classes in the directories and JAR/ZIP files on the class path, as set
by the <tt>CLASSPATH</tt> environment variable or the <tt>-classpath</tt>
command-line option. This class loader is also implemented in Java.</p>
<p class="docText">Class loaders have a <span class="docEmphasis">parent/child</span>
relationship. Every class loader except for the bootstrap class loader has a
parent class loader. A class loader is supposed to give its parent a chance to
load any given class and only load it if the parent has failed. For example,
when the system class loader is asked to load a system class (say, <tt>
java.util.ArrayList</tt>), then it first asks the extension class loader. That
class loader first asks the bootstrap class loader. The bootstrap class loader
finds and loads the class in <tt>rt.jar</tt>, and neither of the other class
loaders searches any further.</p>
<div class="docNote">
<p class="docNoteTitle">NOTE</p>
<table cellSpacing="0" cellPadding="1" width="90%" border="0">
<tr>
<td vAlign="top" width="60">
<img alt="graphics/note.gif" src="note.gif" align="left" border="0" width="54" height="53"><br>
</td>
<td vAlign="top">
<p class="docText">It is entirely possible to implement a class loader
that doesn't delegate class loading to its parent first. Such a class
loader can even load its own version of system classes. However, there
seems no benefit to such an arrangement. There is no security risk
either梐 class can load new code with a class loader, but it can't change
its own class loader.</td>
</tr>
</table>
</div>
<p class="docText">Applets, servlets, and RMI stubs are loaded with custom class
loaders. You can even write your own class loader for specialized purposes. That
lets you carry out specialized security checks before you pass the bytecodes to
the virtual machine. For example, you can write a class loader that can refuse
to load a class that has not been marked as "paid for." The next section shows
you how.</p>
<p class="docText">Given a class loader, you load a new class as follows:</p>
<pre>ClassLoader loader = new MyClassLoader();
String className = ". . .";
Class cl = loader.loadClass(className);
</pre>
<p class="docText">Then that class loads other classes on which it depends.</p>
<p class="docText">With all these class loaders, you may wonder which one is in
charge. Recall again when classes are loaded:</p>
<ol class="docList">
<span style="font-weight: bold" TYPE="1">
<li><span style="font-weight: normal">
<p class="docList">Implicitly, when a class is resolved, that is, when the
classes on which it depends are loaded;</span></li>
<li><span style="font-weight: normal">
<p class="docList">Explicitly, but without a named class loader, by calling
<tt>Class.forName(className);</tt></span></li>
<li><span style="font-weight: normal">
<p class="docList">Through a class loader, by calling <tt>
loader.loadClass(className)</tt>.</span></span></li>
</ol>
<p class="docText">In the first case, the resolution process uses the same class
loader as the one that is loading the original class. In the second case, the
class loader of the class whose method contains the <tt>Class.forName</tt>
instruction is used. In the third case, the specified class loader is in charge.
This is the only way to switch to a new class loader.</p>
<div class="docNote">
<p class="docNoteTitle">CAUTION</p>
<table cellSpacing="0" cellPadding="1" width="90%" border="0">
<tr>
<td vAlign="top" width="60">
<img alt="graphics/caution.gif" src="caution.gif" align="left" border="0" width="54" height="51"><br>
</td>
<td vAlign="top">
<p class="docText">You can run into grief if you drop a JAR file into the
<tt>jre/lib/ext</tt> directory and one of its classes calls <tt>
Class.forName</tt>. That call will <span class="docEmphasis">only</span>
use the extension class loader, and not the system class loader, to find
the class. In particular, the class path is never used. Keep that in mind
before you use the extension directory as a way to minimize your class
file hassles.</td>
</tr>
</table>
</div>
<div class="docNote">
<p class="docNoteTitle">NOTE</p>
<table cellSpacing="0" cellPadding="1" width="90%" border="0">
<tr>
<td vAlign="top" width="60">
<img alt="graphics/note.gif" src="note.gif" align="left" border="0" width="54" height="53"><br>
</td>
<td vAlign="top">
<p class="docText">That pitfall begs the question of what you should do if
you must dynamically load classes in an extension library. You can call
the static <tt>ClassLoader.getSystemClassLoader</tt> method to get the
system class loader. However, that may not be the appropriate class loader
to use in all circumstances. After all, the extension code may have been
called from a class that was loaded with another class loader. To overcome
this problem, every thread has a "context class loader," the class loader
that is most reasonable to use when executing code in the thread. Call <tt>
loadClass</tt> with that class loader instead of calling <tt>Class.forName</tt>:</p>
<pre>Thread t = Thread.currentThread();
ClassLoader loader = t.getContextClassLoader();
Class cl = loader.loadClass(className);
</pre>
<p class="docText">Conversely, before starting a new thread, you can set
the context class loader:</p>
<pre>Thread t = new Thread(. . .);
t.setContextClassLoader(myClassLoader);
t.start();
</pre>
<p class="docText">If no context class loader is set, the thread takes the
context class loader of the parent thread. The main thread of an
application has the system class loader as its context class loader.</td>
</tr>
</table>
</div>
<div class="docNote">
<p class="docNoteTitle">CAUTION</p>
<table cellSpacing="0" cellPadding="1" width="90%" border="0">
<tr>
<td vAlign="top" width="60">
<img alt="graphics/caution.gif" src="caution.gif" align="left" border="0" width="54" height="51"><br>
</td>
<td vAlign="top">
<p class="docText">There is a second pitfall with dropping JAR files into
the <tt>jre/lib/ext</tt> directory. Sometimes, programmers forget about
the files they placed there months ago. Then they scratch their heads when
the class loader seems to ignore the class path, when it is actually
loading long-forgotten classes from the extension directory.</td>
</tr>
</table>
</div>
<p class="docText">Every Java programmer knows that package names are used to
eliminate name conflicts. There are two classes called <tt>Date</tt> in the
standard library, but of course their real names are <tt>java.util.Date</tt> and
<tt>java.sql.Date</tt>. The simple name is only a programmer convenience and
requires the inclusion of appropriate <tt>import</tt> statements. In a running
program, all class names contain their package name.</p>
<p class="docText">It may surprise you, however, that you can have two classes
in the same virtual machine that have the same class <span class="docEmphasis">
and package</span> name. A class is determined by its full name
<span class="docEmphasis">and</span> the class loader. This technique is useful
when loading code from multiple sources. For example, a browser uses separate
instances of the applet class loader class for each web page. This allows the
virtual machine to separate classes from different web pages, no matter what
they are named.</p>
<div class="docNote">
<p class="docNoteTitle">NOTE</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -