|
|
|
Sponsored Link •
|
|
Advertisement
|
Class java.security.AccessController provides a default security
policy enforcement mechanism that uses stack inspection to determine whether potentially unsafe actions
should be permitted. The access controller can't be instantiated. It isn't an object. Rather, it is a bundle of
static methods collected in a single class. The central method of the
AccessController is its static checkPermission()
method, which decides whether or not a particular action is allowed. This method returns
void and takes a reference to a Permission object as its only
parameter. Similar to the check methods of the security manager, if the
AccessController decides the operation should be allowed, its
checkPermission() method simply returns silently. But if the
AccessController decides that an operation should be forbidden, its
checkPermission() method completes abruptly by throwing an
AccessControlException, or one of its subclasses.
As mentioned previously, the concrete SecurityManager's implementation of
the legacy check methods (such as checkRead() and
checkWrite()) simply instantiate an appropriate Permission
object and invoke the concrete SecurityManager's
checkPermission() method. The concrete
SecurityManager's checkPermission() method simply
invokes checkPermission() on the AccessController.
Thus, if you install the concrete SecurityManager, the
AccessController is the ultimate entity that decides whether or not potentially
unsafe actions will be allowed.
The basic algorithm implemented by the AccessController's
checkPermission() method makes certain that every frame on the call stack has
permission to perform the potentially unsafe action. Each stack frame represents some method that has been
invoked by the current thread. Each method is defined in some class. Each class belongs to some protection
domain. And each protection domain contains a set of permissions. Thus, each stack frame is indirectly
associated with a set of permissions. For an action represented by the Permission
object passed to the AccessController's
checkPermission() method to be allowed, the basic algorithm of the
AccessController requires that the permissions associated with each frame on the
call stack must include or imply the Permission passed to
checkPermission().
The AccessController's checkPermission()
method inspects the stack from the top down. As soon as it encounters a frame that doesn't have permission,
it throws an AccessControlException. By throwing the exception, the
AccessController, indicates that the action should not be allowed. On the other
hand, if the checkPermission() method reaches the bottom of the stack without
encountering any frames that don't have permission to perform the potentially unsafe action,
checkPermission() returns silently. By returning rather than throwing an
exception, the AccessController indicates the action should be allowed
The actual algorithm implemented by the AccessController's
checkPermission() method is a bit more complex than the basic algorithm
described here. By invoking any of several doPrivileged() methods of class
AccessController, programs can in effect cause the
AccessController to stop its frame by frame search before it reaches the bottom
of the stack. The doPrivileged() method will be described later in this chapter.
implies() Method To determine whether or not the action represented by the Permission object
passed to the AccessController's checkPermission()
method is included among (or implied by) the permissions associated with the code on the call stack, the
AccessController makes use of an important method named
implies(). The implies() method is declared in class
Permission, as well as in classes PermissionCollection
and ProtectionDomain. implies() takes a
Permission object as its only parameter and returns a boolean
true or false. The implies() method of
class Permission determines whether the permission represented by one
Permission object is naturally implied by the permission represented by a different
Permission object. The implies() methods of
PermissionCollection and ProtectionDomain
determine whether the passed Permission is included among or implied by the
collection of Permission objects encapsulated in the
PermissionCollection or ProtectionDomain.
For example, a permission to read all files in the /tmp directory would naturally
imply a permission to read /tmp/f, a specific file in the /tmp
directory, but not vice versa. If you asked a FilePermission object that represents
the permission to read any file in the /tmp directory if it implies the permission to read
file /tmp/f, the implies() method should return
true. But if you ask a FilePermission object representing the
permission to read /tmp/f if it implies the permission to read any file in the
/tmp directory, the implies() method should return
false.
The Example1 application from the security/ex1
directory of the CD-ROM demonstrates this meaning of implies():
import java.security.Permission;
import java.io.FilePermission;
import java.io.File;
// On CD-ROM in file security/ex1/Example1.java
class Example1 {
public static void main(String[] args) {
char sep = File.separatorChar;
// Read permission for "/tmp/f"
Permission file = new FilePermission(
sep + "tmp" + sep + "f", "read");
// Read permission for "/tmp/*", which
// means all files in the /tmp directory
// (but not any files in subdirectories
// of /tmp)
Permission star = new FilePermission(
sep + "tmp" + sep + "*", "read");
boolean starImpliesFile = star.implies(file);
boolean fileImpliesStar = file.implies(star);
// Prints "Star implies file = true"
System.out.println("Star implies file = "
+ starImpliesFile);
// Prints "File implies star = false"
System.out.println("File implies star = "
+ fileImpliesStar);
}
}
The Example1 application creates two FilePermission
objects, one that represents read permission for a particular directory and another that represents read
permission for a particular file in that same directory. The FilePermission object
referenced from local variable star represents permission to read any file in
/tmp. The FilePermission object referenced from local
variable file represents permission to read file /tmp/f. When
executed, this application prints:
Star implies file = true File implies star = false
The implies() method is used by the
AccessController to determine whether a thread has permission to take actions. If
the checkPermission() method of the AccessController
is invoked to determine whether that thread has permission to read file /tmp/f, for
example, the AccessController can invoke the implies()
method on the ProtectionDomain objects associated with each frame of that
thread's call stack. To each implies() method, the
AccessController can pass the FilePermission object
representing permission to read file /tmp/f that was passed to its
checkPermission() method. The implies() method of
each ProtectionDomain object can invoke implies() on
the PermissionCollection it encapsulates, passing along the same
FilePermission. Each PermissionCollection can in
turn invoke implies() on the Permission objects it contains,
once again passing along a reference to the same FilePermission object. As soon
as a PermissionCollection's implies() method
encounters one Permission object whose implies() method
returns true, the PermissionCollection's
implies() method returns true. Only if none of the
implies() methods of the Permission objects contained in a
PermissionCollection return true does the
PermissionCollection return false. The
ProtectionDomain's implies() method simply returns what
the PermissionCollection's implies() method returns. If
the AccessController gets back a true from the
implies() method of a ProtectionDomain associated with
a particular stack frame, the code represented by that stack frame has permission to perform the potentially
unsafe action.
|
Sponsored Links
|