The Java EE 5 Tutorial

Defining a Security View of Enterprise Beans

You can define a security view of the enterprise beans contained in the ejb-jar file and pass this information along to the deployer. When a security view is passed on to the deployer, the deployer uses this information to define method permissions for security roles. If you don’t define a security view, the deployer will have to determine what each business method does to determine which users are authorized to call each method.

A security view consists of a set of security roles, a semantic grouping of permissions that a given type of users of an application must have to successfully access the application. Security roles are meant to be logical roles, representing a type of user. You can define method permissions for each security role. A method permission is a permission to invoke a specified group of methods of the enterprise beans’ business interface, home interface, component interface, and/or web service endpoints. You can specify an authentication mechanism that will be used to verify the identity of a user.

It is important to keep in mind that security roles are used to define the logical security view of an application. They should not be confused with the user groups, users, principals, and other concepts that exist in the Application Server.

The following sections discuss setting up security roles, authentication mechanisms, and method permissions that define a security view:

Defining Security Roles

Use the @DeclareRoles and @RolesAllowed annotations to define security roles using Java language annotations. The set of security roles used by the application is the total of the security roles defined by the security role names used in the @DeclareRoles and @RolesAllowed annotations.

You can augment the set of security roles defined for the application by annotations using the security-role deployment descriptor element to define security roles, where you use the role-name element to define the name of the security role.

The following example illustrates how to define security roles in a deployment descriptor:

    ...
<assembly-descriptor>
    <security-role>
        <description>
            This role includes the employees of the
            enterprise who are allowed to access the
            employee self-service application. This role
            is allowed only to access his/her own
            information.
        </description>
        <role-name>employee</role-name>
    </security-role>

    <security-role>
        <description>
            This role includes the employees of the human
            resources department. The role is allowed to
             view and update all employee records.
        </description>
        <role-name>hr-department</role-name>
    </security-role>

    <security-role>
        <description>
            This role includes the employees of the payroll
            department. The role is allowed to view and
            update the payroll entry for any employee.
        </description>
        <role-name>payroll-department</role-name>
    </security-role>

    <security-role>
        <description>
            This role should be assigned to the personnel
            authorized to perform administrative functions
            for the employee self-service application.
            This role does not have direct access to
            sensitive employee and payroll information.
        </description>
        <role-name>admin</role-name>
    </security-role>
    ...
</assembly-descriptor>

Linking Security Role References to Security Roles

The security role references used in the components of the application are linked to the security roles defined for the application. In the absence of any explicit linking, a security role reference will be linked to a security role having the same name.

You can explicitly link all the security role references declared in the @DeclareRoles annotation or security-role-ref elements for a component to the security roles defined by the use of annotations (as discussed in Defining Security Roles) and/or in the security-role elements.

You use the role-link element to link each security role reference to a security role. The value of the role-link element must be the name of one of the security roles defined in a security-role element, or by the @DeclareRoles or @RolesAllowed annotations (as discussed in Defining Security Roles). You do not need to use the role-link element to link security role references to security roles when the role-name used in the code is the same as the name of the security-role to which you would be linking.

The following example illustrates how to link the security role reference name payroll to the security role named payroll-department:

...
 <enterprise-beans>
     ...
     <session>
         <ejb-name>AardvarkPayroll</ejb-name>
         <ejb-class>com.aardvark.payroll.PayrollBean</ejb-class>
         ...
         <security-role-ref>
             <description>
                 This role should be assigned to the
                 employees of the payroll department.
                 Members of this role have access to
                 anyone’s payroll record.
                 The role has been linked to the
                 payroll-department role.
             </description>
             <role-name>payroll</role-name>
             <role-link>payroll-department</role-link>
         </security-role-ref>
         ...
     </session>
     ...
 </enterprise-beans>
 ...

Specifying an Authentication Mechanism

Authentications mechanisms are specified in the runtime deployment descriptor. When annotations, such as the @RolesAllowed annotation, are used to protect methods in the enterprise bean, you can configure the Interoperable Object Reference (IOR) to enable authentication for an enterprise application. This is accomplished by adding the <login-config>element to the runtime deployment descriptor, sun-ejb-jar.xml.

You can use the USERNAME-PASSWORD authentication method for an enterprise bean. You can use either the BASIC or CLIENT-CERT authentication methods for web service endpoints.

For more information on specifying an authentication mechanism, read Configuring IOR Security or Example: Securing an Enterprise Bean.

Specifying Method Permissions

If you have defined security roles for the enterprise beans in the ejb-jar file, you can also specify the methods of the business interface, home interface, component interface, and/or web service endpoints that each security role is allowed to invoke.

You can use annotations and/or the deployment descriptor for this purpose. Refer to the following sections for more information on specifying method permissions:

Specifying Method Permissions Using Annotations

The method permissions for the methods of a bean class can be specified on the class, the business methods of the class, or both. Method permissions can be specified on a method of the bean class to override the method permissions value specified on the entire bean class. The following annotations are used to specify method permissions:

The following example code illustrates the use of these annotations:

@RolesAllowed("admin")
public class SomeClass {
    public void aMethod () {...}
    public void bMethod () {...}
    ...
}

@Stateless public class MyBean implements A extends SomeClass {

    @RolesAllowed("HR")
    public void aMethod () {...}

    public void cMethod () {...}
    ...
}

In this example, assuming aMethod, bMethod, and cMethod are methods of business interface A, the method permissions values of methods aMethod and bMethod are @RolesAllowed("HR") and @RolesAllowed("admin") respectively. The method permissions for method cMethod have not been specified.

To clarify, the annotations are not inherited by the subclass per se, they apply to methods of the superclass which are inherited by the subclass. Also, annotations do not apply to CMP entity beans.

An example that uses annotations to specify method permissions is described in Example: Securing an Enterprise Bean.

Specifying Method Permissions Using Deployment Descriptors


Note –

Any values explicitly specified in the deployment descriptor override any values specified in annotations. If a value for a method has not been specified in the deployment descriptor, and a value has been specified for that method by means of the use of annotations, the value specified in annotations will apply. The granularity of overriding is on the per-method basis.


You define the method permissions in the deployment descriptor using the method-permission elements, as discussed below:

Here is some other useful information about setting method permissions using deployment descriptors:

There are three legal styles for composing the method element:

The following example illustrates how security roles are assigned method permissions in the deployment descriptor:

 ...
 <method-permission>
     <role-name>employee</role-name>
     <method>
         <ejb-name>EmployeeService</ejb-name>
         <method-name>*</method-name>
     </method>
 </method-permission>

 <method-permission>
     <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>
 </method-permission>

 <method-permission>
     <role-name>payroll-department</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>
     <method>
         <ejb-name>AardvarkPayroll</ejb-name>
         <method-name>updateSalary</method-name>
     </method>
 </method-permission>

 <method-permission>
     <role-name>admin</role-name>
     <method>
         <ejb-name>EmployeeServiceAdmin</ejb-name>
         <method-name>*</method-name>
     </method>
 </method-permission>
 ...

Mapping Security Roles to Application Server Groups

The Application Server assigns users to principals or groups, rather than to security roles. When you are developing a Java EE application, you don’t need to know what categories of users have been defined for the realm in which the application will be run. In the Java EE platform, the security architecture provides a mechanism for mapping the roles defined in the application to the users or groups defined in the runtime realm.

To map a role name permitted by the application or module to principals (users) and groups defined on the server, use the security-role-mapping element in the runtime deployment descriptor (sun-application.xml, sun-web.xml, or sun-ejb-jar.xml) file. The entry needs to declare a mapping between a security role used in the application and one or more groups or principals defined for the applicable realm of the Application Server. An example for the sun-application.xml file is shown below:

<sun-application>
    <security-role-mapping>
        <role-name>CEO</role-name>
        <principal-name>jschwartz</principal-name>
    </security-role-mapping>
    <security-role-mapping>
        <role-name>ADMIN</role-name>
        <group-name>directors</group-name>
    </security-role-mapping>
</sun-application>

The role name can be mapped to either a specific principal (user), a group, or both. The principal or group names referenced must be valid principals or groups in the current default realm of the Application Server. The role-name in this example must exactly match the role-name in the security-role element of the corresponding web.xml file or the role name defined in the @DeclareRoles or @RolesAllowed annotations.

    Sometimes the role names used in the application are the same as the group names defined on the Application Server. Under these circumstances, you can enable a default principal-to-role mapping on the Application Server using the Admin Console. To enable the default principal-to-role-mapping, follow these steps:

  1. Start the Application Server, then the Admin Console.

  2. Expand the Configuration node.

  3. Select the Security node.

  4. On the Security page, check the Enabled box beside Default Principal to Role Mapping.

For an enterprise application, you can specify the security role mapping at the application layer, in sun-application.xml, or at the module layer, in sun-ejb-jar.xml. When specified at the application layer, the role mapping applies to all contained modules and overrides same-named role mappings at the module layer. The assembler is responsible for reconciling the module-specific role mappings to yield one effective mapping for the application.

Both example applications demonstrate security role mapping. For more information, see Example: Securing an Enterprise Bean and Example: Using the isCallerInRole and getCallerPrincipal Methods.

Propagating Security Identity

You can specify whether a caller’s security identity should be used for the execution of specified methods of an enterprise bean, or whether a specific run-as identity should be used.

Figure 29–2 illustrates this concept.

Figure 29–2 Security Identity Propagation

Diagram of security identity propagation from client
to intermediate container to target container

In this illustration, an application client is making a call to an enterprise bean method in one EJB container. This enterprise bean method, in turn, makes a call to an enterprise bean method in another container. The security identity during the first call is the identity of the caller. The security identity during the second call can be any of the following options:

Configuring a Component’s Propagated Security Identity

You can configure an enterprise bean’s run-as, or propagated, security identity using either of the following:

Alternately, you can use the use-caller-identity element to indicate that you want to use the identity of the original caller, as shown in the code below:

<security-identity>
    <use-caller-identity />
</security-identity>

You must explicitly specify the run-as role name mapping to a given principal in sun-web.xml or sun-ejb-jar.xml if the given roles associate to more than one user principal.

More detail about the elements contained in deployment descriptors is available in the Sun Java System Application Server 9.1 Application Deployment Guide.

In either case, you will have to map the run-as role name to a given principal defined on the Application Server if the given roles associate to more than one user principal. Mapping roles to principals is described in Mapping Security Roles to Application Server Groups.

Trust between Containers

When an enterprise bean is designed so that either the original caller identity or a designated identity is used to call a target bean, the target bean will receive the propagated identity only; it will not receive any authentication data.

There is no way for the target container to authenticate the propagated security identity. However, because the security identity is used in authorization checks (for example, method permissions or with the isCallerInRole() method), it is vitally important that the security identity be authentic. Because there is no authentication data available to authenticate the propagated identity, the target must trust that the calling container has propagated an authenticated security identity.

By default, the Application Server is configured to trust identities that are propagated from different containers. Therefore, there are no special steps that you need to take to set up a trust relationship.