Security is a fundamental part of any enterprise application. You need to be able to restrict who is allowed to access your applications and control what operations application users may perform. The J2EE specifications define a simple role-based security model for EJBs and web components. The JBoss component framework that handles security is the JBossSX extension framework. The JBossSX security extension provides support for both the role-based declarative J2EE security model as well as integration of custom security via a security proxy layer. The default implementation of the declarative security model is based on Java Authentication and Authorization Service (JAAS) login modules and subjects. The security proxy layer allows custom security that cannot be described using the declarative model to be added to an EJB in a way that is independent of the EJB business object. Before getting into the JBoss security implementation details, we will revie EJB and Servlet specification security models as well as JAAS to establish the foundation for these details.
The security model advocated by the J2EE specification is a declarative model. It is declarative in that you describe the security roles and permissions using a standard XML descriptor rather than embedding security into your business component. This isolates security from business-level code because security tends to be a more a function of where the component is deployed, rather than an inherent aspect of the component's business logic. For example, consider an ATM component that is to be used to access a bank account. The security requirements, roles and permissions will vary independent of how one accesses the bank account based on what bank is managing the account, where the ATM machine is deployed, and so on.
Securing a J2EE application is based on the specification of the application security requirements via the standard J2EE deployment descriptors. You secure access to EJBs and web components in an enterprise application by using the ejb-jar.xml and web.xml deployment descriptors. Figure 8.1, “A subset of the EJB 2.0 deployment descriptor content model that shows the security related elements.” and Figure 8.2, “A subset of the Servlet 2.2 deployment descriptor content model that shows the security related elements.” illustrate the security-related elements in the EJB 2.0 and Servlet 2.2 deployment descriptors, respectively.

Figure 8.1. A subset of the EJB 2.0 deployment descriptor content model that shows the security related elements.

Figure 8.2. A subset of the Servlet 2.2 deployment descriptor content model that shows the security related elements.
The purpose and usage of the various security elements given in Figure 8.1, “A subset of the EJB 2.0 deployment descriptor content model that shows the security related elements.” and Figure 8.2, “A subset of the Servlet 2.2 deployment descriptor content model that shows the security related elements.” is discussed in the following subsections.
Both EJBs and servlets may declare one or more security-role-ref elements. This element is used to declare that a component is using the role-name value as an argument to the isCallerInRole(String) method. Using the isCallerInRole method, a component can verify if the caller is in a role that has been declared with a security-role-ref/role-name element. The role-name element value must link to a security-role element through the role-link element. The typical use of isCallerInRole is to perform a security check that cannot be defined using the role based method-permissions elements. However, use of isCallerInRole is discouraged because this results in security logic embedded inside of the component code. Example descriptor fragments that illustrate the security-role-ref element usage are presented in Example 8.4, “An example ejb-jar.xml descriptor fragments which illustrate the security-role element usage.” and Example 8.5, “An example web.xml descriptor fragment which illustrate the security-role element usage.”.
Example 8.1. An example ejb-jar.xml descriptor fragments which illustrate the security-role-ref element usage.
<!-- A sample ejb-jar.xml fragment -->
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>ASessionBean</ejb-name>
...
<security-role-ref>
<role-name>TheRoleICheck</role-name>
<role-link>TheApplicationRole</role-link>
</security-role-ref>
</session>
</enterprise-beans>
...
</ejb-jar>Example 8.2. An example web.xml descriptor fragments which illustrate the security-role-ref element usage.
<web-app>
<servlet>
<servlet-name>AServlet</servlet-name>
...
<security-role-ref>
<role-name>TheServletRole</role-name>
<role-link>TheApplicationRole</role-link>
</security-role-ref>
</servlet>
...
</web-app>
EJBs can optionally declare a security-identity element. New to EJB 2.0 is the capability to specify what identity an EJB should use when it invokes methods on other components. The invocation identity can be that of the current caller, or a specific role. The application assembler uses the security-identity element with a use-caller-identity child element to indicate the current caller's identity should be propagated as the security identity for method invocations made by the EJB. Propagation of the caller's identity is the default used in the absence of an explicit security-identity element declaration.
Alternatively, the application assembler can use the run-as/role-name child element to specify that a specific security role given by the role-name value should be used as the security identity for method invocations made by the EJB. Note that this does not change the caller's identity as seen by EJBContext.getCallerPrincipal(). Rather, the caller's security roles are set to the single role specified by the run-as/role-name element value. One use case for the run-as element is to prevent external clients from accessing internal EJBs. This is accomplished by assigning the internal EJB method-permission elements that restrict access to a role never assigned to an external client. EJBs that need to use internal EJB are then configured with a run-as/role-name equal to the restricted role. An example descriptor fragment that illustrates security-identity element usage is presented in Example 8.3, “An example ejb-jar.xml descriptor fragment which illustrates the security-identity element usage.”.
Example 8.3. An example ejb-jar.xml descriptor fragment which illustrates the security-identity element usage.
<!-- A sample ejb-jar.xml fragment -->
<ejb-jar>
<enterprise-beans>
<session>
<ejb-name>ASessionBean</ejb-name>
<!-- ... -->
<security-identity>
<use-caller-identity/>
</security-identity>
</session>
<session>
<ejb-name>RunAsBean</ejb-name>
<!-- ... -->
<security-identity>
<run-as>
<description>A private internal role</description>
<role-name>InternalRole</role-name>
</run-as>
</security-identity>
</session>
</enterprise-beans>
<!-- ... -->
</ejb-jar>The security role name referenced by either the security-role-ref or security-identity element needs to map to one of the application's declared roles. An application assembler defines logical security roles by declaring security-role elements. The role-name value is a logical application role name like Administrator, Architect, SalesManager, etc.
What is a role? The J2EE specifications note that it is important to keep in mind that the security roles in the deployment descriptor are used to define the logical security view of an application. Roles defined in the J2EE deployment descriptors should not be confused with the user groups, users, principals, and other concepts that exist in the target enterprise's operational environment. The deployment descriptor roles are application constructs with application domain specific names. For example, a banking application might use role names like BankManager, Teller, and Customer.
In JBoss, a security-role is only used to map security-role-ref/role-name values to the logical role that the component role referenced. The user's assigned roles are a dynamic function of the application's security manager, as you will see when we discuss the JBossSX implementation details. JBoss does not require the definition of security-roles in order to declare method permissions. Therefore, the specification of security-role elements is simply a good practice to ensure portability across application servers and for deployment descriptor maintenance. Example descriptor fragments that illustrate security-role usage are presented in Example 8.4, “An example ejb-jar.xml descriptor fragments which illustrate the security-role element usage.” and Example 8.5, “An example web.xml descriptor fragment which illustrate the security-role element usage.”.
Example 8.4. An example ejb-jar.xml descriptor fragments which illustrate the security-role element usage.
<!-- A sample ejb-jar.xml fragment -->
<ejb-jar>
<!-- ... -->
<assembly-descriptor>
<security-role>
<description>The single application role</description>
<role-name>TheApplicationRole</role-name>
</security-role>
</assembly-descriptor>
</ejb-jar>An application assembler can set the roles that are allowed to invoke an EJB's home and remote interface methods through method-permission element declarations. Each method-permission element contains one or more role-name child elements that define the logical roles allowed access the EJB methods as identified by method child elements. As of EJB 2.0, you can now specify an unchecked element instead of the role-name element to declare that any authenticated user can access the methods identified by method child elements. In addition, you can declare that no one should have access to a method with the exclude-list element. If an EJB has methods that have not been declared as accessible by a role using a method-permission element, the EJB methods default to being excluded from use. This is equivalent to defaulting the methods into the exclude-list.
There are three supported styles of method element declarations.
<method>
<ejb-name>EJBNAME</ejb-name>
<method-name>*</method-name>
</method><method>
<ejb-name>EJBNAME</ejb-name>
<method-name>METHOD</method-name>
</method><method>
<ejb-name>EJBNAME</ejb-name>
<method-name>METHOD</method-name>
<method-params>
<method-param>PARAMETER_1</method-param>
<!-- ... -->
<method-param>PARAMETER_N</method-param>
</method-params>
</method>The optional method-intf element can be used to differentiate methods with the same name and signature that are defined in both the home and remote interfaces of an enterprise bean. Example 8.6, “An example ejb-jar.xml descriptor fragment which illustrates the method-permission element usage.” provides examples of the method-permission element usage.
Example 8.6. An example ejb-jar.xml descriptor fragment which illustrates the method-permission element usage.
<ejb-jar>
<assembly-descriptor>
<method-permission>
<description>The employee and temp-employee roles may access any
method of the EmployeeService bean </description>
<role-name>employee</role-name>
<role-name>temp-employee</role-name>
<method>
<ejb-name>EmployeeService</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<description>The employee role may access the findByPrimaryKey,
getEmployeeInfo, and the updateEmployeeInfo(String) method of
the AardvarkPayroll bean </description>
<role-name>employee</role-name>
<method>
<ejb-name>AardvarkPayroll</ejb-name>
<method-name>findByPrimaryKey</method-name>
</method>
<method>
<ejb-name>AardvarkPayroll</ejb-name>
<method-name>getEmployeeInfo</method-name>
</method>
<method>
<ejb-name>AardvarkPayroll</ejb-name>
<method-name>updateEmployeeInfo</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</method>
</method-permission>
<method-permission>
<description>The admin role may access any method of the
EmployeeServiceAdmin bean </description>
<role-name>admin</role-name>
<method>
<ejb-name>EmployeeServiceAdmin</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<method-permission>
<description>Any authenticated user may access any method of the
EmployeeServiceHelp bean</description>
<unchecked/>
<method>
<ejb-name>EmployeeServiceHelp</ejb-name>
<method-name>*</method-name>
</method>
</method-permission>
<exclude-list>
<description>No fireTheCTO methods of the EmployeeFiring bean may be
used in this deployment</description>
<method>
<ejb-name>EmployeeFiring</ejb-name>
<method-name>fireTheCTO</method-name>
</method>
</exclude-list>
</assembly-descriptor>
</ejb-jar>In a web application, security is defined by the roles allowed access to content by a URL pattern that identifies the protected content. This set of information is declared using the web.xml security-constraint element. The content to be secured is declared using one or more web-resource-collection elements. Each web-resource-collection element contains an optional series of url-pattern elements followed by an optional series of http-method elements. The url-pattern element value specifies a URL pattern against which a request URL must match for the request to correspond to an attempt to access secured content. The http-method element value specifies a type of HTTP request to allow.
The optional user-data-constraint element specifies the requirements for the transport layer of the client to server connection. The requirement may be for content integrity (preventing data tampering in the communication process) or for confidentiality (preventing reading while in transit). The transport-guarantee element value specifies the degree to which communication between client and server should be protected. Its values are NONE, INTEGRAL, or CONFIDENTIAL. A value of NONE means that the application does not require any transport guarantees. A value of INTEGRAL means that the application requires the data sent between the client and server be sent in such a way that it can't be changed in transit. A value of CONFIDENTIAL means that the application requires the data be transmitted in a fashion that prevents other entities from observing the contents of the transmission. In most cases, the presence of the INTEGRAL or CONFIDENTIAL flag indicates that the use of SSL is required.
The optional login-config is used to configure the authentication method that should be used, the realm name that should be used for this application, and the attributes that are needed by the form login mechanism. The auth-method child element specifies the authentication mechanism for the web application. As a prerequisite to gaining access to any web resources that are protected by an authorization constraint, a user must have authenticated using the configured mechanism. Legal values for auth-method are BASIC, DIGEST, FORM, or CLIENT-CERT. The realm-name child element specifies the realm name to use in HTTP basic and digest authorization. The form-login-config child element specifies the log in as well as error pages that should be used in form-based login. If the auth-method value is not FORM, form-login-config and its child elements are ignored.
As an example, the web.xml descriptor fragment given in Example 8.7, “ A web.xml descriptor fragment which illustrates the use of the security-constraint and related elements.” indicates that any URL lying under the web application /restricted path requires an AuthorizedUser role. There is no required transport guarantee and the authentication method used for obtaining the user identity is BASIC HTTP authentication.
Example 8.7. A web.xml descriptor fragment which illustrates the use of the security-constraint and related elements.
<web-app>
<!-- ... -->
<security-constraint>
<web-resource-collection>
<web-resource-name>Secure Content</web-resource-name>
<url-pattern>/restricted/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>AuthorizedUser</role-name>
</auth-constraint>
<user-data-constraint>
<transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>
</security-constraint>
<!-- ... -->
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>The Restricted Zone</realm-name>
</login-config>
<!-- ... -->
<security-role>
<description>The role required to access restricted content </description>
<role-name>AuthorizedUser</role-name>
</security-role>
</web-app>The J2EE security elements that have been covered describe only the security requirements from the application's perspective. Since J2EE security elements declare logical roles, the application deployer maps the roles from the application domain onto the deployment environment. The J2EE specifications omit these application-server-specific details. In JBoss, mapping the application roles onto the deployment environment entails specifying a security manager that implements the J2EE security model using JBoss server specific deployment descriptors. We will avoid discussion the details of this step for now. The details behind the security configuration will be discussed when we describe the generic JBoss server security interfaces in Section 8.3, “The JBoss Security Model”.
The default implementation of the JBossSX framework is based on the JAAS API. It is important that you understand the basic elements of the JAAS API to understand the implementation details of JBossSX. This section provides an introduction to JAAS to prepare you for the JBossSX architecture discussion. Additional details on the JAAS package can be found at the JAAS home page at: http://java.sun.com/products/jaas/.
The JAAS 1.0 API consists of a set of Java packages designed for user authentication and authorization. It implements a Java version of the standard Pluggable Authentication Module (PAM) framework and compatibly extends the Java 2 Platform's access control architecture to support user-based authorization. JAAS was first released as an extension package for JDK 1.3 and is bundled with JDK 1.4+. Because the JBossSX framework uses only the authentication capabilities of JAAS to implement the declarative role-based J2EE security model, this introduction focuses on only that topic.
Much of this section's material is derived from the JAAS 1.0 Developers Guide, so if you are familiar with its content you can skip ahead to the JBossSX architecture discussion in Section 8.4, “The JBoss Security Extension Architecture”
JAAS authentication is performed in a pluggable fashion. This permits Java applications to remain independent from underlying authentication technologies and allows the JBossSX security manager to work in different security infrastructures. Integration with a security infrastructure can be achieved without changing the JBossSX security manager implementation. All that needs to change is the configuration of the authentication stack that JAAS uses.
The JAAS core classes can be broken down into three categories: common, authentication, and authorization. The following list presents only the common and authentication classes because these are the specific classes used to implement the functionality of JBossSX covered in this chapter.
Common classes:
Authentication classes:
To authorize access to resources, applications first need to authenticate the request's source. The JAAS framework defines the term subject to represent a request's source. The Subject class is the central class in JAAS. A Subject represents information for a single entity, such as a person or service. It encompasses the entity's principals, public credentials, and private credentials. The JAAS APIs use the existing Java 2 java.security.Principal interface to represent a principal, which is essentially just a typed name.
During the authentication process, a subject is populated with associated identities, or principals. A subject may have many principals. For example, a person may have a name principal (John Doe), a social security number principal (123-45-6789), and a username rincipal (johnd), all of which help distinguish the subject from other subjects. To retrieve the principals associated with a swubject, two methods are available:
public Set getPrincipals() {...}
public Set getPrincipals(Class c) {...} The first method returns all princiaps contained in the subject. The second method only returns those principals that are instances of Class c or one of its subclasses. An empty set will be returned if the subject has no matching principals. Note that the java.security.acl.Group interface is a subinterface of java.security.Principal, and so an instance in the principals set may represent a logical grouping of other principals or groups of principals.
Authentication of a subject requires a JAAS login. The login procedure consists of the following steps:
The LoginContext class provides the basic methods for authenticating subjects and offers a way to develop an application independent of the underlying authentication technology. The LoginContext consults a Configuration to determine the authentication services configured for a particular application. LoginModule classes represent the authentication services. Therefore, you can plug in different login modules into an application without changing the application itself. Example 8.8, “An illustration of the steps of the authentication process from the application perspective.” provides code fragments that illustrate the steps required by an application to authenticate a subject.
Example 8.8. An illustration of the steps of the authentication process from the application perspective.
CallbackHandler handler = new MyHandler();
LoginContext lc = new LoginContext("some-config", handler);
try {
lc.login();
Subject subject = lc.getSubject();
} catch(LoginException e) {
System.out.println("authentication failed");
e.printStackTrace();
}
// Perform work as authenticated Subject
// ...
// Scope of work complete, logout to remove authentication info
try {
lc.logout();
} catch(LoginException e) {
System.out.println("logout failed");
e.printStackTrace();
}
// A sample MyHandler class
class MyHandler
implements CallbackHandler
{
public void handle(Callback[] callbacks) throws
IOException, UnsupportedCallbackException
{
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
NameCallback nc = (NameCallback)callbacks[i];
nc.setName(username);
} else if (callbacks[i] instanceof PasswordCallback) {
PasswordCallback pc = (PasswordCallback)callbacks[i];
pc.setPassword(password);
} else {
throw new UnsupportedCallbackException(callbacks[i],
"Unrecognized Callback");
}
}
}
}Developers integrate with an authentication technology by creating an implementation of the LoginModule interface. This allows different authentication technologies to be plugged into an application by administrator. Multiple LoginModules can be chained together to allow for more than one authentication technology as part of the authentication process. For example, one LoginModule may perform username/password-based authentication, while another may interface to hardware devices such as smart card readers or biometric authenticators. The life cycle of a LoginModule is driven by the LoginContext object against which the client creates and issues the login method. The process consists of a two phases. The steps of the process are as follows:
When a LoginModule must communicate with the user to obtain authentication information, it uses a CallbackHandler object. Applications implement the CallbackHandler interface and pass it to the LoginContext, which forwards it directly to the underlying login modules. Login modules use the CallbackHandler both to gather input from users, such as a password or smart-card PIN number, and to supply information to users, such as status information. By allowing the application to specify the CallbackHandler, underlying LoginModules remain independent from the different ways applications interact with users. For example, a CallbackHandler's implementation for a GUI application might display a window to solicit user input. On the other hand, a callbackhandler's implementation for a non-GUI environment, such as an application server, might simply obtain credential information using an application server API. The callbackhandler interface has one method to implement:
void handle(Callback[] callbacks) throws java.io.IOException, UnsupportedCallbackException;
The last authentication class to cover is the Callback interface. This is a tagging interface for which several default implementations are provided, including NameCallback and PasswordCallback that were used in Example 8.8, “An illustration of the steps of the authentication process from the application perspective.” LoginModule s use a Callback to request information required by the authentication mechanism the LoginModule encapsulates. LoginModule s pass an array of Callback s directly to the CallbackHandler.handle method during the authentication's login phase. If a callbackhandler does not understand how to use a Callback object passed into the handle method, it throws an UnsupportedCallbackException to abort the login call.
Similar to the rest of the JBoss architecture, security at the lowest level is defined as a set of interfaces for which alternate implementations may be provided. There are three basic interfaces that define the JBoss server security layer: org.jboss.security.AuthenticationManager, org.jboss.security.RealmMapping, and org.jboss.security.SecurityProxy. Figure 8.3, “The key security model interfaces and their relationship to the JBoss server EJB container elements.” shows a class diagram of the security interfaces and their relationship to the EJB container architecture.

Figure 8.3. The key security model interfaces and their relationship to the JBoss server EJB container elements.
The light blue classes represent the security interfaces while the yellow classes represent the EJB container layer. The two interfaces required for the implementation of the J2EE security model are the org.jboss.security.AuthenticationManager and org.jboss.security.RealmMapping. The roles of the security interfaces presented in Figure 8.3, “The key security model interfaces and their relationship to the JBoss server EJB container elements.” are summarized in the following list.
Note that the AuthenticationManager, RealmMapping and SecurityProxy interfaces have no association to JAAS related classes. Although the JBossSX framework is heavily dependent on JAAS, the basic security interfaces required for implementation of the J2EE security model are not. The JBossSX framework is simply an implementation of the basic security plug-in interfaces that are based on JAAS. The component diagram presented in Figure 8.4, “The relationship between the JBossSX framework implementation classes and the JBoss server EJB container layer.” illustrates this fact. The implication of this plug-in architecture is that you are free to replace the JAAS-based JBossSX implementation classes with your own custom security manager implementation that does not make use of JAAS, if you so desire. You'll see how to do this when you look at the JBossSX MBeans available for the configuration of JBossSX in Figure 8.4, “The relationship between the JBossSX framework implementation classes and the JBoss server EJB container layer.”.

Figure 8.4. The relationship between the JBossSX framework implementation classes and the JBoss server EJB container layer.
Recall that our discussion of the J2EE standard security model ended with a requirement for the use of JBoss server specific deployment descriptor to enable security. The details of this configuration is presented here, as this is part of the generic JBoss security model. Figure 8.5, “The security element subsets of the JBoss server jboss.xml and jboss-web.xml deployment descriptors.” shows the JBoss-specific EJB and web application deployment descriptor's security-related elements.

Figure 8.5. The security element subsets of the JBoss server jboss.xml and jboss-web.xml deployment descriptors.
The value of a security-domain element specifies the JNDI name of the security manager interface implementation that JBoss uses for the EJB and web containers. This is an object that implements both of the AuthenticationManager and RealmMapping interfaces. When specified as a top-level element it defines what security domain in effect for all EJBs in the deployment unit. This is the typical usage because mixing security managers within a deployment unit complicates inter-component operation and administration.
To specify the security domain for an individual EJB, you specify the security-domain at the container configuration level. This will override any top-level security-domain element.
The unauthenticated-principal element specifies the name to use for the Principal object returned by the EJBContext.getUserPrincpal method when an unauthenticated user invokes an EJB. Note that this conveys no special permissions to an unauthenticated caller. Its primary purpose is to allow unsecured servlets and JSP pages to invoke unsecured EJBs and allow the target EJB to obtain a non-null Principal for the caller using the getUserPrincipal method. This is a J2EE specification requirement.
The security-proxy element identifies a custom security proxy implementation that allows per-request security checks outside the scope of the EJB declarative security model without embedding security logic into the EJB implementation. This may be an implementation of the org.jboss.security.SecurityProxy interface, or just an object that implements methods in the home, remote, local home or local interfaces of the EJB to secure without implementing any common interface. If the given class does not implement the SecurityProxy interface, the instance must be wrapped in a SecurityProxy implementation that delegates the method invocations to the object. The org.jboss.security.SubjectSecurityProxy is an example SecurityProxy implementation used by the default JBossSX installation.
Take a look at a simple example of a custom SecurityProxy in the context of a trivial stateless session bean. The custom SecurityProxy validates that no one invokes the bean's echo method with a four-letter word as its argument. This is a check that is not possible with role-based security; you cannot define a FourLetterEchoInvoker role because the security context is the method argument, not a property of the caller. The code for the custom SecurityProxy is given in Example 8.9, “The example 1 custom EchoSecurityProxy implementation that enforces the echo argument-based security constraint.”, and the full source code is available in the src/main/org/jboss/chap8/ex1 directory of the book examples. The associated jboss.xml descriptor that installs the EchoSecurityProxy as the custom proxy for the EchoBean is given in Example 8.10, “The jboss.xml descriptor which configures the EchoSecurityProxy as the custom security proxy for the EchoBean.”.
Example 8.9. The example 1 custom EchoSecurityProxy implementation that enforces the echo argument-based security constraint.
package org.jboss.chap8.ex1;
import java.lang.reflect.Method;
import javax.ejb.EJBContext;
import org.apache.log4j.Category;
import org.jboss.security.SecurityProxy;
/** A simple example of a custom SecurityProxy implementation
* that demonstrates method argument based security checks.
* @author Scott.Stark@jboss.org
* @version $Revision: 1.15 $
*/
public class EchoSecurityProxy implements SecurityProxy
{
Category log = Category.getInstance(EchoSecurityProxy.class);
Method echo;
public void init(Class beanHome, Class beanRemote,
Object securityMgr)
throws InstantiationException
{
log.debug("init, beanHome="+beanHome
+ ", beanRemote="+beanRemote
+ ", securityMgr="+securityMgr);
// Get the echo method for equality testing in invoke
try {
Class[] params = {String.class};
echo = beanRemote.getDeclaredMethod("echo", params);
} catch(Exception e) {
String msg = "Failed to finde an echo(String) method";
log.error(msg, e);
throw new InstantiationException(msg);
}
}
public void setEJBContext(EJBContext ctx)
{
log.debug("setEJBContext, ctx="+ctx);
}
public void invokeHome(Method m, Object[] args)
throws SecurityException
{
// We don't validate access to home methods
}
public void invoke(Method m, Object[] args, Object bean)
throws SecurityException
{
log.debug("invoke, m="+m);
// Check for the echo method
if (m.equals(echo)) {
// Validate that the msg arg is not 4 letter word
String arg = (String) args[0];
if (arg == null || arg.length() == 4)
throw new SecurityException("No 4 letter words");
}
// We are not responsible for doing the invoke
}
}
Example 8.10. The jboss.xml descriptor which configures the EchoSecurityProxy as the custom security proxy for the EchoBean.
<jboss>
<security-domain>java:/jaas/other</security-domain>
<enterprise-beans>
<session>
<ejb-name>EchoBean</ejb-name>
<security-proxy>org.jboss.chap8.ex1.EchoSecurityProxy</security-proxy>
</session>
</enterprise-beans>
</jboss> The EchoSecurityProxy checks that the method to be invoked on the bean instance corresponds to the echo(String) method loaded the init method. If there is a match, the method argument is obtained and its length compared against 4 or null. Either case results in a SecurityException being thrown. Certainly this is a contrived example, but only in its application. It is a common requirement that applications must perform security checks based on the value of method arguments. The point of the example is to demonstrate how custom security beyond the scope of the standard declarative security model can be introduced independent of the bean implementation. This allows the specification and coding of the security requirements to be delegated to security experts. Since the security proxy layer can be done independent of the bean implementation, security can be changed to match the deployment environment requirements.
Now test the custom proxy by running a client that attempts to invoke the EchoBean.echo method with the arguments Hello and Four as illustrated in this fragment:
public class ExClient
{
public static void main(String args[])
throws Exception
{
Logger log = Logger.getLogger("ExClient");
log.info("Looking up EchoBean");
InitialContext iniCtx = new InitialContext();
Object ref = iniCtx.lookup("EchoBean");
EchoHome home = (EchoHome) ref;
Echo echo = home.create();
log.info("Created Echo");
log.info("Echo.echo('Hello') = "+echo.echo("Hello"));
log.info("Echo.echo('Four') = "+echo.echo("Four"));
}
} The first call should succeed, while the second should fail due to the fact that Four is a four-letter word. Run the client as follows using Ant from the examples directory:
[nr@toki examples]$ ant -Dchap=chap8 -Dex=1 run-example
run-example1:
[copy] Copying 1 file to /tmp/jboss-3.2.6/server/default/deploy
[echo] Waiting for 5 seconds for deploy...
[java] [INFO,ExClient] Looking up EchoBean
[java] [INFO,ExClient] Created Echo
[java] [INFO,ExClient] Echo.echo('Hello') = Hello
[java] Exception in thread "main" java.rmi.ServerException: RemoteException occurred
in server thread; nested exception is:
[java] java.rmi.AccessException: SecurityException; nested exception is:
[java] java.lang.SecurityException: No 4 letter words
...
[java] at org.jboss.chap8.ex1.ExClient.main(ExClient.java:28)
[java] Caused by: java.rmi.AccessException: SecurityException; nested exception is:
[java] java.lang.SecurityException: No 4 letter words
...The result is that the echo('Hello') method call succeeds as expected and the echo('Four') method call results in a rather messy looking exception, which is also expected. The above output has been truncated to fit in the book. The key part to the exception is that the SecurityException("No 4 letter words") generated by the EchoSecurityProxy was thrown to abort the attempted method invocation as desired.
The preceding discussion of the general JBoss security layer has stated that the JBossSX security extension framework is an implementation of the security layer interfaces. This is the primary purpose of the JBossSX framework. The details of the implementation are interesting in that it offers a great deal of customization for integration into existing security infrastructures. A security infrastructure can be anything from a database or LDAP server to a sophisticated security software suite. The integration flexibility is achieved using the pluggable authentication model available in the JAAS framework.
The heart of the JBossSX framework is org.jboss.security.plugins.JaasSecurityManager. This is the default implementation of the AuthenticationManager and RealmMapping interfaces. Figure 8.6, “The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.” shows how the JaasSecurityManager integrates into the EJB and web container layers based on the security-domain element of the corresponding component deployment descriptor.

Figure 8.6. The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.
Figure 8.6, “The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.” depicts an enterprise application that contains both EJBs and web content secured under the security domain jwdomain. The EJB and web containers have a request interceptor architecture that includes a security interceptor, which enforces the container security model. At deployment time, the security-domain element value in the jboss.xml and jboss-web.xml descriptors is used to obtain the security manager instance associated with the container. The security interceptor then uses the security manager to perform its role. When a secured component is requested, the security interceptor delegates security checks to the security manager instance associated with the container.
The JBossSX JaasSecurityManager implementation, shown in Figure 8.6, “The relationship between the security-domain component deployment descriptor value, the component container and the JaasSecurityManager.” as the JaasSecurityMgr component, performs security checks based on the information associated with the Subject instance that results from executing the JAAS login modules configured under the name matching the security-domain element value. We will drill into the JaasSecurityManager implementation and its use of JAAS in the following section.
The JaasSecurityManager uses the JAAS packages to implement the AuthenticationManager and RealmMapping interface behavior. In particular, its behavior derives from the execution of the login module instances that are configured under the name that matches the security domain to which the JaasSecurityManager has been assigned. The login modules implement the security domain's principal authentication and role-mapping behavior. Thus, you can use the JaasSecurityManager across different security domains simply by plugging in different login module configurations for the domains.
To illustrate the details of the JaasSecurityManager's usage of the JAAS authentication process, you will walk through a client invocation of an EJB home method invocation. The prerequisite setting is that the EJB has been deployed in the JBoss server and its home interface methods have been secured using method-permission elements in the ejb-jar.xml descriptor, and it has been assigned a security domain named jwdomain using the jboss.xml descriptor security-domain element.

Figure 8.7. An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.
Figure 8.7, “An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.” provides a view of the client to server communication we will discuss. The numbered steps shown are:
The security domain under which the EJB is secured determines the choice of login modules. The security domain name is used as the login configuration entry name passed to the LoginContext constructor. The EJB security domain is jwdomain. If the JAAS login authenticates the user, a JAAS Subject is created that contains the following in its PrincipalsSet:
The final step of the security interceptor check is to verify that the authenticated user has permission to invoke the requested method This is labeled as Server Side Authorization in Figure 8.7, “An illustration of the steps involved in the authentication and authorization of a secured EJB home method invocation.”. Performing the authorization this entails the following steps:
Every secured EJB method invocation, or secured web content access, requires the authentication and authorization of the caller because security information is handled as a stateless attribute of the request that must be presented and validated on each request. This can be an expensive operation if the JAAS login involves client-to-server communication. Because of this, the JaasSecurityManager supports the notion of an authentication cache that is used to store principal and credential information from previous successful logins. You can specify the authentication cache instance to use as part of the JaasSecurityManager configuration as you will see when the associated MBean service is discussed in following section. In the absence of any user-defined cache, a default cache that maintains credential information for a configurable period of time is used.
The JaasSecurityManagerService MBean service manages security managers. Although its name begins with Jaas, the security managers it handles need not use JAAS in their implementation. The name arose from the fact that the default security manager implementation is the JaasSecurityManager. The primary role of the JaasSecurityManagerService is to externalize the security manager implementation. You can change the security manager implementation by providing an alternate implementation of the AuthenticationManager and RealmMapping interfaces. Of course this is optional because, by default, the JaasSecurityManager implementation is used.
The second fundamental role of the JaasSecurityManagerService is to provide a JNDI javax.naming.spi.ObjectFactory implementation to allow for simple code-free management of the JNDI name to security manager implementation mapping. It has been mentioned that security is enabled by specifying the JNDI name of the security manager implementation via the security-domain deployment descriptor element. When you specify a JNDI name, there has to be an object-binding there to use. To simplify the setup of the JNDI name to security manager bindings, the JaasSecurityManagerService manages the association of security manager instances to names by binding a next naming system reference with itself as the JNDI ObjectFactory under the name java:/jaas. This allows one to use a naming convention of the form java:/jaas/XYZ as the value for the security-domain element, and the security manager instance for the XYZ security domain will be created as needed for you. The security manager for the domain XYZ is created on the first lookup against the java:/jaas/XYZ binding by creating an instance of the class specified by the SecurityManagerClassName attribute using a constructor that takes the name of the security domain. For example, consider the following container security configuration snippet:
<jboss>
<!-- Configure all containers to be secured under the "hades" security domain -->
<security-domain>java:/jaas/hades</security-domain>
<!-- ... -->
</jboss> Any lookup of the name java:/jaas/hades will return a security manager instance that has been associated with the security domain named hades. This security manager will implement the AuthenticationManager and RealmMapping security interfaces and will be of the type specified by the JaasSecurityManagerService SecurityManagerClassName attribute.
The JaasSecurityManagerService MBean is configured by default for use in the standard JBoss distribution, and you can often use the default configuration as is. The configurable attributes of the JaasSecurityManagerService include:
The JaasSecurityManagerService also supports a number of useful operations. These include flushing any security domain authentication cache at runtime, getting the list of active users in a security domain authentication cache, and any of the security manager interface methods.
Flushing a security domain authentication cache can be used to drop all cached credentials when the underlying store has been updated and you want the store state to be used immediately. The MBean operation signature is: public void flushAuthenticationCache(String securityDomain).
This can be invoked programmatically using the following code snippet:
MBeanServer server = ...;
String jaasMgrName = "jboss.security:service=JaasSecurityManager";
ObjectName jaasMgr = new ObjectName(jaasMgrName);
Object[] params = {domainName};
String[] signature = {"java.lang.String"};
server.invoke(jaasMgr, "flushAuthenticationCache", params, signature);Getting the list of active users provides a snapshot of the Principals keys in a security domain authentication cache that are not expired. The MBean operation signature is: public List getAuthenticationCachePrincipals(String securityDomain).
This can be invoked programmatically using the following code snippet:
MBeanServer server = ...;
String jaasMgrName = "jboss.security:service=JaasSecurityManager";
ObjectName jaasMgr = new ObjectName(jaasMgrName);
Object[] params = {domainName};
String[] signature = {"java.lang.String"};
List users = (List) server.invoke(jaasMgr, "getAuthenticationCachePrincipals",
params, signature);The security manager has a few additional access methods.
public boolean isValid(String securityDomain, Principal principal, Object credential);
public Principal getPrincipal(String securityDomain, Principal principal);
public boolean doesUserHaveRole(String securityDomain, Principal principal,
Object credential, Set roles);
public Set getUserRoles(String securityDomain, Principal principal, Object credential);They provide access to the corresponding AuthenticationManager and RealmMapping interface method of the associated security domain named by the securityDomain argument.
The org.jboss.security.plugins.JaasSecurityDomain is an extension of JaasSecurityManager that adds the notion of a KeyStore, aJSSE KeyManagerFactory and a TrustManagerFactory for supporting SSL and other cryptographic use cases. The additional configurable attributes of the JaasSecurityDomain include:
KeyStoreURL: A URL to the location of the KeyStore database. This is used to obtain an InputStream to initialize the KeyStore. If the string is not a value URL, it iss treated as a file.
KeyStorePass: The password associated with the KeyStore database contents. The KeyStorePass is also used in combination with the Salt and IterationCount attributes to create a PBE secret key used with the encode/decode operations. The KeyStorePass attribute value format is one of the following:
The plaintext password for the KeyStore The toCharArray() value of the string is used without any manipulation.
A command to execute to obtain the plaintext password. The format is {EXT}... where the ... is the exact command line that will be passed to the Runtime.exec(String) method to execute a platform-specific command. The first line of the command output is used as the password.
A class to create to obtain the plaintext password. The format is {CLASS}classname[:ctorarg] where the [:ctorarg] is an optional string that will be passed to the constructor when instantiating the the classname. The password is obtained from classname by invoking a toCharArray() method if found, otherwise, the toString() method is used.
Salt: The PBEParameterSpec salt value.
IterationCount: The PBEParameterSpec iteration count value.
ManagerServiceName: Sets the JMX object name string of the security manager service MBean. This is used to register the defaults to register the JaasSecurityDomain as a the security manager under java:/jaas/<domain> where <domain> is the name passed to the MBean constructor. The name defaults to jboss.security:service=JaasSecurityManager.
LoadSunJSSEProvider: A flag indicating if the Sun com.sun.net.ssl.internal.ssl.Provider security provider should be loaded on startup. This is needed when using the Sun JSSE jars without them installed as an extension with JDK 1.3. This should be set to false with JDK 1.4 or when using an alternate JSSE provider. This flag currently defaults to true.
JBoss uses a custom implementation of the javax.security.auth.login.Configuration class that is provided by the org.jboss.security.auth.login.XMLLoginConfig MBean. This configuration implementation uses an XML format that conforms to the DTD given by Figure 8.8, “The XMLLoginConfig DTD”.
The name attribute of the application-policy is the login configuration name. This corresponds to the portion of the jboss.xml and jboss-web.xml security-domain element value after the java:/jaas/ prefix. The code attribute of the login-module element specifies the class name of the login module implementation. The flag attribute controls the overall behavior of the authentication stack. The allowed values and measnings are:
Zero or more module-option elements may be specified as child elements of a login-module. These define name/value string pairs that are made available to the login module during initialization. The name attribute specifies the option name while the module-option body provides the value. An example login configuration is given in Example 8.11, “A sample login module configuration suitable for use with XMLLoginConfig”.
Example 8.11. A sample login module configuration suitable for use with XMLLoginConfig
<policy>
<application-policy name="srp-test">
<authentication>
<login-module code="org.jboss.security.srp.jaas.SRPCacheLoginModule"
flag="required">
<module-option name="cacheJndiName">srp-test/AuthenticationCache</module-option>
</login-module>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule"
flag="required">
<module-option name="password-stacking">useFirstPass</module-option>
</login-module>
</authentication>
</application-policy>
</policy>The XMLLoginConfig MBean supports the following attributes:
The MBean also supports the following operations that allow one to dynamically extend the login configurations at runtime. Note that any operation that attempts to alter login configuration requires a javax.security.auth.AuthPermission("refreshLoginConfiguration") when running with a security manager. The org.jboss.chap8.service.SecurityConfig service demonstrates how this can be used to add/remove a deployment specific scurity configuration dynamically.
The installation of the custom javax.security.auth.login.Configuration is managed by the org.jboss.security.plugins.SecurityConfig MBean. There is one configurable attribute:
In addition to allowing for a custom JAAS login configuration implementation, this service allows configurations to be chained together in a stack at runtime. This allows one to push a login configuration onto the stack and latter pop it. This is a feature used by the security unit tests to install custom login configurations into a default JBoss installation. Pusing a new configuration is done using:
public void pushLoginConfig(String objectName) throws
JMException, MalformedObjectNameException;The objectName parameters specifies an MBean similar to the LoginConfig attribute. The current login configuration may be removed using:
public void popLoginConfig() throws JMException;
The JaasSecurityManager implementation allows complete customization of the authentication mechanism using JAAS login module configurations. By defining the login module configuration entry that corresponds to the security domain name you have used to secure access to your J2EE components, you define the authentication mechanism and integration implementation.
The JBossSX framework includes a number of bundled login modules suitable for integration with standard security infrastructure store protocols such as LDAP and JDBC. It also includes standard base class implementations that help enforce the expected LoginModule to Subject usage pattern that was described in theSection 8.4.7, “Writing Custom Login Modules”. These implementations allow for easy integration of your own authentication protocol, if none of the bundled login modules prove suitable. In this section we will first describe the useful bundled login modules and their configuration, and then end with a discussion of how to create your own custom LoginModule implementations for use with JBoss.
The IdentityLoginModule is a simple login module that associates the principal specified in the module options with any subject authenticated against the module. It creates a SimplePrincipal instance using the name specified by the principal option. Although this is certainly not an appropriate login module for production strength authentication, it can be of use in development environments when you want to test the security associated with a given principal and associated roles.
The supported login module configuration options include:
A sample legacy Sun format login configuration entry that would authenticate all users as the principal named jduke and assign role names of TheDuke, and AnimatedCharacter is:
testIdentity {
org.jboss.security.auth.spi.IdentityLoginModule required
principal=jduke
roles=TheDuke,AnimatedCharater;
};The corresponding XMLLoginConfig format is:
<policy>
<application-policy name="testIdentity">
<authentication>
<login-module code="org.jboss.security.auth.spi.IdentityLoginModule"
flag="required">
<module-option name="principal">jduke</module-option>
<module-option name="roles">TheDuke,AnimatedCharater</module-option>
</login-module>
</authentication>
</application-policy>
</policy> To add this entry to a JBoss server login cofiguration found in the default configuration file set you would modify the conf/default/auth.conf file of the JBoss distribution.
The UsersRolesLoginModule is another simple login module that supports multiple users and user roles, and is based on two Java Properties formatted text files. The username-to-password mapping file is called users.properties and the username-to-roles mapping file is called roles.properties. The properties files are loaded during initialization using the initialize method thread context class loader. This means that these files can be placed into the J2EE deployment JAR, the JBoss configuration directory, or any directory on the JBoss server or system classpath. The primary purpose of this login module is to easily test the security settings of multiple users and roles using properties files deployed with the application.
The users.properties file uses a username=password format with each user entry on a separate line as show here:
username1=password1 username2=password2 ...
The roles.properties file uses as username=role1,role2,... format with an optional group name value. For example:
username1=role1,role2,... username1.RoleGroup1=role3,role4,... username2=role1,role3,...
The username.XXX form of property name is used to assign the username roles to a particular named group of roles where the XXX portion of the property name is the group name. The username=... form is an abbreviation for username.Roles=..., where the Roles group name is the standard name the JaasSecurityManager expects to contain the roles which define the users permissions.
The following would be equivalent definitions for the jduke username:
jduke=TheDuke,AnimatedCharacter jduke.Roles=TheDuke,AnimatedCharacter
The supported login module configuration options include the following: