It’s incredibly hard to understand the JACC specification (at least for me). Here it is in pragmatic, condensed terms. Clever insight is courtesy of Ron Monzillo; fumbling incompetence is mine alone.
You write a JACC implementation when you want to use a third-party authorization system. There are other reasons, too. JACC expresses Java EE role-based security mechanisms in terms of
java.security.Policy and provides the means to carve the authorization rulebase up into subsets that pertain to individual Java EE modules. It also provides the means to determine that a
Permission is explicitly excluded (
java.security.Policy can only indicate that it is not granted, which could be because it is excluded or simply not handled).
A JACC implementation typically consists of a
Policy subclass, a
PolicyConfiguration implementation, and a
PolicyConfigurationFactory subclass. It’s possible to write just the last two and to have them puke out policy files that the regular old
com.sun.security.provider.PolicyFile class installed in every JVM by default can parse, but usually you write all three if you have cause to write a JACC implementation at all.
You write a
PolicyConfiguration implementation to set up and produce your rulebase for a given Java EE module. (JACC calls your rulebase a “policy context”.) By “rulebase”, I mean (usually) the
Permissions, granted and excluded, that define your authorization rules. Your rulebase might be a collection of files, a
HashMap, a table in a database, etc. etc. The main thing is that your rulebase needs to be accessible by your
java.security.Policy subclass (or more correctly by whatever
Policy is installed in the system, reachable from the static
You write a
PolicyConfigurationFactory subclass to produce instances of your
Policy subclass will be used in some fashion by the JVM to evaluate all permission checks, not just by your Java EE module, so it needs to be able to check things like
SecurityPermissions and the like (i.e. things you don’t usually think of when you think about Java EE). Typically you’ll delegate some of these calls to the
Policy that’s installed already.
(For some reason, JACC refers to your
Policy subclass as a “policy provider”. Every time you see “policy provider”, think
PolicyConfiguration class needs to be thread-safe. It has a very well-defined lifecycle, but the salient points are that it is initially in a state where it is set up (“open”), then it is locked down via its
commit() method (“in service”) which has the extremely important side effect of conceptually producing the rulebase (“policy context”) that was just configured and making it available for consultation. Only after its rulebase (policy context) is so produced (placed in service) may your
Policy subclass consult it.
Once your rulebase has been created and placed in service by virtue of your
PolicyConfiguration‘s having been committed, your
Policy subclass will use it to render authorization decisions. All security calls will eventually flow through the
Policy#implies(ProtectionDomain, Permission) method. Your implementation of this method must consult your rulebase, but only the proper subset of your rulebase. Which subset? The one that is in effect for the current Java EE module that’s making the current authorization check.
To determine which subset of your rulebase to consider, your
Policy subclass calls
PolicyContext#getContextID() to obtain a key. This key identifies effectively which Java EE module is making the security call, and hence which subset of your rulebase your
Policy implementation needs to check during its
implies(ProtectionDomain, Permission) call.
Policy subclass, armed with this key, looks up the appropriate rulebase subset (the appropriate policy context). Typically this is either a
HashMap lookup, or a consultation of a file on disk, or the execution of a particular kind of
SELECT query with an appropriate
If the key is
null, then no special rulebase subset is in effect, and only what the JACC specification calls the “default policy context” is in effect. Basically this means that no Java EE module has made this authorization call and you must consult the JVM-wide
Policy for your authorization decision. (The default policy context is always in effect; more on that later.)
If the key is not
null, then the rulebase subset—the current policy context, in JACC-speak—is now responsible for answering the authorization question. It may exclude the
Permission, in which case no matter what else happens the
Permission must not be granted, or it may grant it (provided that the default policy context does not exclude it). Again: if for any reason a given permission is found to be excluded, then
java.security.Policy#implies(ProtectionDomain, Permission) must return
The default policy context, however it is implemented, forms a part of every authorization decision. That means if somehow it is possible to determine that the default policy context excludes a given
Permission (not possible with the regular old
java.security.Policy class) then that
Permission must be excluded and
Policy#implies(ProtectionDomain, Permission) must return