📄 _chapter 9.htm
字号:
<p class="docText">Change 3C to 3B and save the class file. Then try running the
<tt>VerifierTest</tt> program. You get an error message:</p>
<pre>Exception in thread "main" java.lang.VerifyError: (class: Verifi-
erTest, method:fun signature: ()I) Accessing value from unini-
tialized register 1
</pre>
<p class="docText">That is good梩he virtual machine detected our modification.</p>
<p class="docText">Now run the program with the <tt>-noverify</tt> (or <tt>-Xverify:none</tt>)
option.</p>
<pre>java -noverify VerifierTest
</pre>
<p class="docText">The <tt>fun</tt> method returns a seemingly random value.
This is actually 2 plus the value that happened to be stored in the variable <tt>
n</tt>, which never was initialized. Here is a typical printout:</p>
<pre>1 + 2 = 15102330
</pre>
<p class="docText">To see how browsers handle verification, we wrote this
program to run either as an application or an applet. Load the applet into a
browser, using a file URL such as</p>
<pre>file:///C:/CoreJavaBook/v2ch9/VerifierTest/VerifierTest.html
</pre>
<p class="docText">Then, you see an error message displayed indicating that
verification has failed (see <a class="docLink" href="#ch09fig03">Figure 9-3</a>).</p>
<center>
<h5 id="ch09fig03" class="docFigureTitle">Figure 9-3. Loading a corrupted class file raises a
method verification error</h5>
<p>
<img alt="graphics/09fig03.gif" src="09fig03.gif" border="0" width="500" height="351"><br>
</p>
</center>
<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">There is a curious hole in the verifier in the Java
interpreter that has been known by many people for a long time but that
persists for compatibility reasons. Suppose you have two class files <tt>
A.java</tt> and <tt>B.java</tt> like this:</p>
<pre>public class A { public int field; }
public class B
{
public static void main(String[] args)
{
System.out.println(new A().field);
}
}
</pre>
<p class="docText">This program compiles and runs, of course. Now edit
<span class="docEmphasis">only</span> the file <tt>A.java</tt> to make <tt>
field</tt> private. Recompile only that file. The resulting program should
fail verification since <tt>B</tt> now attempts to access a private field
of <tt>A</tt>. However, up to SDK 1.4, the program will run and merrily
access the private field. Only if you run the Java interpreter with the
<tt>-Xverify:all</tt> option will the error be caught.</p>
<p class="docText">The reason is backwards compatibility with an obscure
and ill-considered optimization in JDK 1.0梥ee
<a class="docLink" href="http://developer.java.sun.com/developer/bugparade/bugs/4030988.html" target="_blank">
http://developer.java.sun.com/developer/bugParade/bugs/4030988.html</a>.
This is not considered a security risk because only classes loaded from
the local file system are exempt from verification.</td>
</tr>
</table>
</div>
<h5 id="ch09list03" class="docExampleTitle">Example 9-3 VerifierTest.java</h5>
<pre> 1. import java.awt.*;
2. import java.applet.*;
3.
4. /**
5. This application demonstrates the bytecode verifier of
6. the virtual machine. If you use a hex editor to modify the
7. class file, then the virtual machine should detect the
8. tampering.
9. */
10. public class VerifierTest extends Applet
11. {
12. public static void main(String[] args)
13. {
14. System.out.println("1 + 2 == " + fun());
15. }
16.
17. /**
18. A function that computes 1 + 2
19. @return 3, if the code has not been corrupted
20. */
21. public static int fun()
22. {
23. int m;
24. int n;
25. m = 1;
26. n = 2;
27. // use hex editor to change to "m = 2" in class file
28. int r = m + n;
29. return r;
30. }
31.
32. public void paint(Graphics g)
33. {
34. g.drawString("1 + 2 == " + fun(), 20, 20);
35. }
36. }
</pre>
<h3 class="docSection1Title" id="c9s3">Security Managers and Permissions</h3>
<p class="docText">Once a class has been loaded into the virtual machine by a
class loader or by the default class loading mechanism and checked by the
verifier, the third security mechanism of the Java platform springs into action:
the <span class="docEmphasis">security manager.</span> A security manager is a
class that controls whether a specific operation is permitted. Operations
checked by a security manager include:</p>
<ul>
<li>
<p class="docList">Whether the current thread can create a new class loader;</li>
<li>
<p class="docList">Whether the current thread can create a subprocess;</li>
<li>
<p class="docList">Whether the current thread can halt the virtual machine;</li>
<li>
<p class="docList">Whether the current thread can load a dynamic link library;</li>
<li>
<p class="docList">Whether a class can access a member of another class;</li>
<li>
<p class="docList">Whether the current thread can access a specified package;</li>
<li>
<p class="docList">Whether the current thread can define classes in a
specified package;</li>
<li>
<p class="docList">Whether the current thread can access or modify system
properties;</li>
<li>
<p class="docList">Whether the current thread can read from or write to a
specified file;</li>
<li>
<p class="docList">Whether the current thread can delete a specified file;</li>
<li>
<p class="docList">Whether the current thread can accept a socket connection
from a specified host and port number;</li>
<li>
<p class="docList">Whether the current thread can open a socket connection to
the specified host and port number;</li>
<li>
<p class="docList">Whether the current thread can wait for a connection
request on a specified local port number;</li>
<li>
<p class="docList">Whether the current thread can use IP multicast;</li>
<li>
<p class="docList">Whether the current thread can invoke a <tt>stop</tt>, <tt>
suspend</tt>, <tt>resume</tt>, <tt>destroy</tt>, <tt>setPriority/setMaxPriority</tt>,
<tt>setName</tt>, or <tt>setDaemon</tt> method of a given thread or thread
group;</li>
<li>
<p class="docList">Whether the current thread can set a socket or stream
handler factory;</li>
<li>
<p class="docList">Whether a class can start a print job;</li>
<li>
<p class="docList">Whether a class can access the system clipboard;</li>
<li>
<p class="docList">Whether a class can access the AWT event queue;</li>
<li>
<p class="docList">Whether the current thread is trusted to bring up a
top-level window.</li>
</ul>
<p class="docText">The default behavior when running Java applications is that
<span class="docEmphasis">no</span> security manager is installed, so all these
operations are permitted. The appletviewer, on the other hand, immediately
installs a security manager (called <tt>AppletSecurity</tt>) that is quite
restrictive.</p>
<p class="docText">For example, applets are not allowed to exit the virtual
machine. If they try calling the <tt>exit</tt> method, then a security exception
is thrown. Here is what happens in detail. The <tt>exit</tt> method of the <tt>
Runtime</tt> class calls the <tt>checkExit</tt> method of the security manager.
Here is the entire code of the <tt>exit</tt> method.</p>
<pre>public void exit(int status)
{
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkExit(status);
exitInternal(status);
}
</pre>
<p class="docText">The security manager now checks if the exit request came from
the browser or an individual applet. If the security manager agrees with the
exit request, then the <tt>checkExit</tt> method simply returns, and normal
processing continues. However, if the security manager doesn't want to grant the
request, the <tt>checkExit</tt> method throws a <tt>SecurityException</tt>.</p>
<p class="docText">The <tt>exit</tt> method continues only if no exception
occurred. It then calls the <span class="docEmphasis">private native</span> <tt>
exitInternal</tt> method that actually terminates the virtual machine. There is
no other way of terminating the virtual machine, and since the <tt>exitInternal</tt>
method is private, it cannot be called from any other class. Thus, any code that
attempts to exit the virtual machine must go through the <tt>exit</tt> method
and thus through the <tt>checkExit</tt> security check without triggering a
security exception.</p>
<p class="docText">Clearly, the integrity of the security policy depends on
careful coding. The providers of system services in the standard library must be
careful to always consult the security manager before attempting any sensitive
operation.</p>
<p class="docText">When you run a Java application, the default is that no
security manager is running. Your program can install a specific security
manager by a call to the static <tt>setSecurityManager</tt> method in the <tt>
System</tt> class. Once your program installs a security manager, any attempt to
install a second security manager only succeeds if the first security manager
agrees to be replaced. This is clearly essential; otherwise, a bad applet could
install its own security manager. Thus, while it is possible to have multiple
class loaders, a program in the Java programming language can be governed by
only one security manager. It is up to the implementor of that security manager
to decide whether to grant all classes the same access or whether to take the
origins of the classes into account before deciding what to do.</p>
<p class="docText">The default security manager of the Java 2 platform allows
both programmers and system administrators fine-grained control over individual
security permissions. We describe these features in the following section.
First, we give you an overview of the Java 2 platform security model. Then, we
show how you can control permissions with <span class="docEmphasis">policy
files.</span> Finally, you will see how you can define your own permission types
and how you can extend the default security manager class.</p>
<h4 class="docSection2Title" id="ch09lev2sec2">Java 2 Platform Security</h4>
<p class="docText">JDK 1.0 had a very simple security model: local classes had
full permissions, and remote classes were confined to the
<span class="docEmphasis">sandbox:</span> the applet security manager denied all
access to local resources. JDK 1.1 implemented a slight modification: remote
code that was signed by a trusted entity was granted the same permissions as
local classes. However, both versions of the JDK provided an all-or-nothing
approach. Programs either had full access or they had to play in the sandbox.</p>
<p class="docText">The Java 2 platform has a much more flexible mechanism. A
<span class="docEmphasis">security policy</span> maps <span class="docEmphasis">
code sources to permission sets</span> (see <a class="docLink" href="#ch09fig04">
Figure 9-4</a>).</p>
<center>
<h5 id="ch09fig04" class="docFigureTitle">Figure 9-4. A security policy</h5>
<p>
<img alt="graphics/09fig04.gif" src="09fig04.gif" border="0" width="500" height="294"><br>
</p>
</center>
<p class="docText">A <span class="docEmphasis">code source</span> has two
properties: the <span class="docEmphasis">code location</span> (for example, a
code base URL or a JAR file) and <span class="docEmphasis">certificates.</span>
You will see later in this chapter how code can be certified by trusted parties.</p>
<p class="docText">A <span class="docEmphasis">permission</span> is any property
that is checked by a security manager. SDK 1.2 implementation supports a number
of permission classes, each of which encapsulates the details of a particular
permission. For example, the following instance of the <tt>FilePermission</tt>
class states that it is ok to read and write any file in the <tt>/tmp</tt>
directory.</p>
<pre>FilePermission p = new FilePermission("/tmp/*", "read,write");
</pre>
<p class="docText">More importantly, the default implementation of the <tt>
Policy</tt> class in SDK 1.2 reads permissions from a <span class="docEmphasis">
permission file.</span> Inside a permission file, the same read permission is
expressed as</p>
<pre>permission java.io.FilePermission "/tmp/*", "read,write";
</pre>
<p class="docText">We discuss permission files in the next section.</p>
<p class="docText"><a class="docLink" href="#ch09fig05">Figure 9-5</a> shows the
hierarchy of permission classes in SDK 1.2.</p>
<center>
<h5 id="ch09fig05" class="docFigureTitle">Figure 9-5. Permission hierarchy in JDK 1.2</h5>
<p>
<img alt="graphics/09fig05.gif" src="09fig05.gif" border="0" width="500" height="364"><br>
</p>
</center>
<p class="docText">In the preceding section, you saw that the <tt>
SecurityManager</tt> class has security check methods such as <tt>checkExit</tt>.
These methods exist only for the convenience of the programmer and for backward
compatibility. All of them call one of the two following methods:</p>
<pre>void checkPermission(Permission p)
void checkPermission(Permission p, Object context)
</pre>
<p class="docText">The second method is used if one thread carries out a
security check for another thread. The <tt>context</tt> encapsulates the call
stack at the time of the check. (See Gong's book for details on how to generate
and use these context objects.)</p>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -