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
|