JBoss.orgCommunity Documentation

Chapter 4. Environment

4.1. Security
4.1.1. Authenticating with JAAS
4.1.2. Authorization with JAAS
4.2. Execution contexts
4.3. Summary

The various components of JBoss DNA are designed as plain old Java objects, or POJOs. And rather than making assumptions about their environment, each component instead requires that any external dependencies necessary for it to operate must be supplied to it. This pattern is known as Dependency Injection, and it allows the components to be simpler and allows for a great deal of flexibility and customization in how the components are configured. And, JBoss DNA will soon provide a higher-level component that leverages the JBoss Microcontainer to automatically assemble and wire together all the lower-level components.

JBoss DNA uses the Java Authentication and Authorization Service (JAAS) for its security mechanism. Not only is this the standard approach for authenticating and authorizing in Java, but it also enables JBoss DNA to integrate existing security systems.

There are quite a few JAAS providers available, but one of the best and most powerful providers is JBoss Security, which is the open source security framework used by JBoss. JBoss Security offers a number of JAAS login modules, including:

  • User-Roles Login Module is a simple javax.security.auth.login.LoginContext implementation that uses usernames and passwords stored in a properties file.

  • Client Login Module prompts the user for their username and password.

  • Database Server Login Module uses a JDBC database to authenticate principals and associate them with roles.

  • LDAP Login Module uses an LDAP directory to authenticate principals. Two implementations are available.

  • Certificate Login Module authenticates using X509 certificates, obtaining roles from either property files or a JDBC database.

  • Operating System Login Module authenticates using the operating system's mechanism.

and many others. Plus, JBoss Security also provides other capabilities, such as using XACML policies or using federated single sign-on. For more detail, see the JBoss Security project.

JBoss DNA defers to JAAS to authenticate clients creating repository connections (known as JCR Sessions if using the JCR API), and generally expects the client application to obtain the JAAS LoginContext or . These are then passed to JBoss DNA, which merely verifies that authentication has been done.

As we'll see in the next section, JBoss DNA has the notion of an ExecutionContext that can be created using JAAS login or access control contexts. These execution contexts therefore contain information about the subject.

We'll also see in the chapter on JCR how JAAS can be used for authentication when JCR Sessions are created.

One of the objects that must be supplied to many JBoss DNA components is an ExecutionContext. Some components require this context to be passed into individual methods, allowing the context to vary with each method invocation. Other components require the context to be provided before it's used, and will use that context for all its operations (until it is given a different one).

What does an ExecutionContext represent? Quite simply, it's the set of objects that define the environment or context in which the method or component is currently operating. It includes a way for recording and reporting errors and problems. It includes the ability to create class loaders given a classpath of class loader names. It also includes information about the current user. It includes access to factories that can be used to create and convert property values. And it includes factories for working with namespaces and fully-qualified names. In fact, as JBoss DNA evolves, more things may need to be added. Here is what the ExecutionContext interface looks like:

public interface ExecutionContext extends ClassLoaderFactory {

    /**
     * Get the factories that should be used to create values for {@link Property properties}.
     * @return the property value factory; never null
     */
    ValueFactories getValueFactories();

    /**
     * Get the namespace registry for this context.
     * @return the namespace registry; never null
     */
    NamespaceRegistry getNamespaceRegistry();

    /**
     * Get the factory for creating {@link Property} objects.
     * @return the property factory; never null
     */
    PropertyFactory getPropertyFactory();

    /**
     * Get the current JAAS access control context.
     * @return the access control context; may be null
     */
    AccessControlContext getAccessControlContext();

    /**
     * Get the current JAAS login context.
     * @return the login context; may be null
     */
    LoginContext getLoginContext();

    /**
     * Get the JAAS subject for which this context was created.
     * @return the subject; never null
     */
    Subject getSubject();

    /**
     * Return a logger associated with this context. This logger records only those activities within the 
     * context and provide a way to capture the context-specific activities. All log messages are also
     * sent to the system logger, so classes that log via this mechanism should <i>not</i> also 
     * {@link Logger#getLogger(Class) obtain a system logger}.
     * @param clazz the class that is doing the logging
     * @return the logger, named after clazz; never null
     */
    Logger getLogger( Class<?> clazz );

    /**
    * Return a logger associated with this context. This logger records only those activities within the 
    * context and provide a way to capture the context-specific activities. All log messages are also
    * sent to the system logger, so classes that log via this mechanism should <i>not</i> also 
    * {@link Logger#getLogger(Class) obtain a system logger}.
     * @param name the name for the logger
     * @return the logger, named after clazz; never null
     */
    Logger getLogger( String name );
}

Notice that ExecutionContext extends the ClassLoaderFactory interface described in the previous chapter.

The fact that so many of the JBoss DNA components take ExecutionContext instances gives us some interesting possibilities. For example, one execution context instance can be used as the highest-level (or "application-level") context for all of the services (e.g., RepositoryService, SequencingService, etc.). Then, an execution context could be created for each user that will be performing operations, and that user's context can be passed around to not only provide security information about the user but also to allow the activities being performed to be recorded for user feedback, monitoring and/or auditing purposes.

While execution contexts may sound complicated, they're actually very simple to use. In fact, JBoss DNA provides an factory interface for creating ExecutionContext instances. Not surprisingly it's called ExecutionContextFactory and it has methods for creating contexts using JAAS login or access control contexts. JBoss DNA even provides a BasicExecutionContextFactory implementation that can be created using its no-arg constructor.

The following code fragment shows how easy it is to create various execution contexts:

ExecutionContextFactory factory = new BasicExecutionContextFactory();
ExecutionContext context1 = factory.create();

// Create a context for a user, authenticating using JAAS ...
CallbackHandler callbackHandler = ...
LoginContext loginContext = new LoginContext("username",callbackHandler);
ExecutionContext context2 = factory.create(loginContext);

These contexts (or the context factory) can then be passed to the various components as needed.

In this chapter, we covered security and environment topics as used throughout JBoss DNA. The next chapter will cover JBoss DNA repositories, including the connector framework, how DNA's JCR implementation works with connectors, what connectors are available (and how to use them), and how to write your own connector.