Skip Headers

Oracle® Application Server Containers for J2EE Security Guide 10g Release 2 (10.1.2) B14013-02 |
| Library | Product | Contents | Index

Previous | Next |

# 12 Configuring EJB Security

This chapter discusses security issues affecting EJBs. It discusses the following topics:

- EJB JNDI Security Properties

- Configuring Security

For full information about EJBs, see the Oracle Application Server Containers for J2EE Enterprise JavaBeans Developer's Guide.

## EJB JNDI Security Properties

There are two JNDI properties that are specific to security. You can either set these within the `jndi.properties` file or within your EJB implementation.

### JNDI Properties in jndi.properties

If setting the JNDI properties within the `jndi.properties` file, set the properties as follows. Make sure that this `jndi.properties` file is accessible from the classpath.

When you access EJBs in a remote container, you must pass valid credentials to this container. Stand-alone clients define their credentials in the `jndi.properties` file deployed with the client code.

    java.naming.security.principal=username
    java.naming.security.credentials=password

### JNDI Properties within Code Implementation

As in the preceding section, set the principal user name and credentials, but in your Java code. For example, JavaBeans running within the container pass their credentials within the `InitialContext`, which is created to look up the remote EJBs.

For instance, to pass JNDI security properties within the `Hashtable` environment, set these as shown in the following example:

    Hashtable env = new Hashtable();
    env.put("java.naming.provider.url", "ormi://myhost/ejbsamples");
    env.put("java.naming.factory.initial",
          "oracle.j2ee.server.ApplicationClientInitialContextFactory");
    env.put(Context.SECURITY_PRINCIPAL, "guest");
    env.put(Context.SECURITY_CREDENTIALS, "welcome");
    Context ic = new InitialContext (env);
    Object homeObject = ic.lookup("java:comp/env/employeeBean");

    // Narrow the reference to a TemplateHome.
    EmployeeHome empHome =
       (EmployeeHome) PortableRemoteObject.narrow(homeObject,
       EmployeeHome.class);

Note: `ApplicationClientInitialContextFactory` is in the file `oc4jclient.jar`.

## Configuring Security

EJB security involves two realms: granting permissions if you download into a browser and configuring your application for authentication and authorization. This section covers the following:

- Granting Permissions in Browser

- Authenticating and Authorizing EJB Applications

- Specifying Credentials in EJB Clients

### Granting Permissions in Browser

If you download the EJB application as a client where the security manager is active, you must grant the following permissions before you can execute:

    permission java.net.SocketPermission "*:*", "connect,resolve";
    permission java.lang.RuntimePermission "createClassLoader";
    permission java.lang.RuntimePermission "getClassLoader";
    permission java.util.PropertyPermission "*", "read";
    permission java.util.PropertyPermission "LoadBalanceOnLookup", "read,write";

### Authenticating and Authorizing EJB Applications

For EJB authentication and authorization, you define the principals under which each method executes by configuring of the EJB deployment descriptor. The container enforces that the user who is trying to execute the method is the same as defined within the deployment descriptor.

The EJB deployment descriptor enables you to define security roles under which each method is allowed to execute. These methods are mapped to users or groups in the OC4J-specific deployment descriptor. The users and groups are defined within your designated security user managers, which uses either the JAZN or XML user manager.

See Also: Oracle Application Server Containers for J2EE User's Guide and Oracle Application Server Containers for J2EE Services Guide for a description of security user managers

For authentication and authorization, this section focuses on XML configuration within the EJB deployment descriptors. EJB authorization is specified within the EJB and OC4J-specific deployment descriptors. You can manage the authorization piece of your security within the deployment descriptors, as follows:

- The EJB deployment descriptor describes access rules using logical roles.

- The OC4J-specific deployment descriptor maps the logical roles to concrete users and groups, which are defined either the JAZN or XML user managers.

Users and groups are identities known by the container. Roles are the logical identities each application uses to indicate access rights to its different objects. The user name / password pairs can be digital certificates and, in the case of SSL, private key pairs.

Thus, the definition and mapping of roles is demonstrated in Figure 12-1.

Figure 12-1 Role Mapping

Description of "Figure 12-1 Role Mapping"

Defining users, groups, and roles are discussed in the following sections:

- Specifying Users and Groups

- Specifying Logical Roles in the EJB Deployment Descriptor

- Specifying Unchecked Security for EJB Methods

- Specifying the run-as Security Identity

- Mapping Logical Roles to Users and Groups

- Specifying a Default Role Mapping for Undefined Methods

- Specifying Users and Groups by the Client

#### Specifying Users and Groups

OC4J supports the definition of users and groups—either shared by all deployed applications or specific to given applications. You define shared or application-specific users and groups within either the JAZN or XML user managers.

See Also: Oracle Application Server Containers for J2EE User's Guide and Oracle Application Server Containers for J2EE Services Guide for specific instructions

#### Specifying Logical Roles in the EJB Deployment Descriptor

As shown in Figure 12-2, you can use a logical name for a role within your bean implementation, and map this logical name to the correct security role or user. The mapping of the logical name to a database role is specified in the OC4J-specific deployment descriptor.

See Also: "Mapping Logical Roles to Users and Groups"

Figure 12-2 Security Mapping

Description of "Figure 12-2 Security Mapping"

If you use a logical name for a database role within your bean implementation for methods such as `isCallerInRole`, you can map the logical name to an actual database role by doing the following:

1. Declare the logical name within the `<enterprise-beans>` section `<security-role-ref>` element. For example, to define a role used within the purchase order example, you may have checked, within the bean implementation, to see if the caller had authorization to sign a purchase order. Thus, the caller would have to be signed in under a correct role. In order for the bean to not need to be aware of database roles, you can check `isCallerInRole` on a logical name, such as `POMgr`, because only purchase order managers can sign off on the order. Thus, you would define the logical security role, `POMgr` in the `<role-name>` element within the `<enterprise-beans>` section, as follows:

       <enterprise-beans>
       ...
         <security-role-ref>
           <role-name>POMgr</role-name>
           <role-link>myMgr</role-link>
         </security-role-ref>
       </enterprise-beans>

   The `<role-link>` element within the `<security-role-ref>` element can be the actual database role, which is defined further within the `<assembly-descriptor>` section. Alternatively, it can be another logical name, which is still defined more in the `<assembly-descriptor>` section and is mapped to an actual database role within the Oracle-specific deployment descriptor.

   Note: The `<security-role-ref>` element is not generally required. You specify it when using security context methods within your bean.

2. Define the role and the methods that it applies to. In the purchase order example, any method executed within the `PurchaseOrder` bean must have authorized itself as `myMgr`. Note that `PurchaseOrder` is the name declared in the ```<ejb-name>` element.

   Thus, the following defines the role as `myMgr`, the EJB as `PurchaseOrder`, and all methods by denoting the "`*`" symbol.

   Note: The `myMgr` role in the `<security-role>` element is the same as the `<role-link>` element within the `<enterprise-beans>` section. This ties the logical name of `POMgr` to the `myMgr` definition.

       <assembly-descriptor>
         <security-role>
           <description>Role needed purchase order authorization</description>
           <role-name>myMgr</role-name>
         </security-role>
         <method-permission>
           <role-name>myMgr</role-name>
           <method>
             <ejb-name>PurchaseOrder</ejb-name>
             <method-name>*</method-name>
           </method>
         </method-permission>
       ...
       </assembly-descriptor>

After performing both steps, you can refer to `POMgr` within the bean implementation and the container translates `POMgr` to `myMgr`.

Note: If you define different roles within the `<method-permission>` element for methods in the same EJB, the resulting permission is a union of all the method permissions defined for the methods of this bean.

The `<method>` subelement of the `<method-permission>` element is used to specify the security role for one or more methods within an interface or implementation. According to the EJB specification, this definition can be of one of the following forms:

1. Defining all methods within a bean by specifying the bean name and using the "`*`" character to denote all methods within the bean, as follows:

       <method-permission>
         <role-name>myMgr</role-name>
         <method>
           <ejb-name>EJBNAME</ejb-name>
           <method-name>*</method-name>
         </method>
       </method-permission>

2. Defining a specific method that is uniquely identified within the bean. Use the appropriate interface name and method name, as follows:

       <method-permission>
         <role-name>myMgr</role-name>
         <method>
           <ejb-name>myBean</ejb-name>
           <method-name>myMethodInMyBean</method-name>
         </method>
       </method-permission>

   Note: If there are multiple methods with the same overloaded name, the element of this style refers to all the methods with the overloaded name.

3. Defining a method with a specific signature among many overloaded versions, as follows:

       <method-permission>
         <role-name>myMgr</role-name>
         <method>
           <ejb-name>myBean</ejb-name>
           <method-name>myMethod</method-name>
           <method-params>
             <method-param>javax.lang.String</method-param>
             <method-param>javax.lang.String</method-param>
           </method-params>
         </method>
       </method-permission>

   The parameters are the fully-qualified Java types of the input parameters of the method. If the method has no input arguments, the <`method-params`> element contains no elements.

#### Specifying Unchecked Security for EJB Methods

If you want certain methods to not be checked for security roles, you define these methods as unchecked, as follows:

    <method-permission>
      <unchecked/>
      <method>
         <ejb-name>EJBNAME</ejb-name>
         <method-name>*</method-name>
      </method>
    </method-permission>

Instead of a `<role-name>` element defined, you define an `<unchecked>` element. When executing any methods in the `EJBNAME` bean, the container does not check for security. Unchecked methods always override any other role definitions.

#### Specifying the run-as Security Identity

You can specify that all methods of an EJB execute under a specific identity. That is, the container does not check different roles for permission to run specific methods; instead, the container executes all of the EJB methods under the specified security identity. You can specify a particular role or the caller identity as the security identity.

Specify the run-as security identity in the `<security-identity>` element, which is contained in the `<enterprise-beans>` section. The following XML demonstrates that the `POMgr` is the role under which all the entity bean methods execute.

    <enterprise-beans>
      <entity>
      ...
        <security-identity>
           <run-as>
             <role-name>POMgr</role-name>
           </run-as>
        </security-identity>
      ...
      </entity>
    </enterprise-beans>

Alternatively, the following XML example demonstrates how to specify that all methods of the bean execute under the identity of the caller:

    <enterprise-beans>
      <entity>
        ...
        <security-identity>
           <use-caller-identity/>
        </security-identity>
        ...
      </entity>
    </enterprise-beans>

#### Mapping Logical Roles to Users and Groups

You can use logical roles or actual users and groups in the EJB deployment descriptor. However, if you use logical roles, you must map them to the actual users and groups defined either in the JAZN or XML user managers.

Map the logical roles defined in the application deployment descriptors to JAZN or XML user manager users or groups through the `<security-role-mapping>` element in the OC4J-specific deployment descriptor.

- The `name` attribute of this element defines the logical role that is to be mapped.

- The `<group>` or `<user>` element maps the logical role to a group or user name. This group or user must be defined in the JAZN or XML user manager configuration.

See Also: Oracle Application Server Containers for J2EE User's Guide and Oracle Application Server Containers for J2EE Services Guide for a description of the JAZN and XML user managers

Example 12-1 Mapping Logical Role to Actual Role

This example maps the logical role `POMGR` to the `managers` group in the `orion-ejb-jar.xml` file. Any user that can log in as part of this group is considered to have the `POMGR` role; thus, it can execute the methods of `PurchaseOrderBean`.

    <security-role-mapping name="POMGR">
      <group name="managers" />
    </security-role-mapping>

Note: You can map a logical role to a single group or to several groups.

To map this role to a specific user, do the following:

    <security-role-mapping name="POMGR">
      <user name="guest" />
    </security-role-mapping>

Lastly, you can map a role to a specific user within a specific group, as follows:

    <security-role-mapping name="POMGR">
      <group name="managers" />
      <user name="guest" />
    </security-role-mapping>

As shown in Figure 12-3, the logical role name for `POMGR` defined in the EJB deployment descriptor is mapped to `managers` within the OC4J-specific deployment descriptor in the `<security-role-mapping>` element.

Figure 12-3 Security Mapping

Description of "Figure 12-3 Security Mapping"

Notice that the `<role-name>` in the EJB deployment descriptor is the same as the name attribute in the `<security-role-mapping>` element in the OC4J-specific deployment descriptor. This is what identifies the mapping.

#### Specifying a Default Role Mapping for Undefined Methods

If any methods have not been associated with a role mapping, they are mapped to the default security role through the `<default-method-access>` element in the `orion-ejb-jar.xml` file. The following is the automatic mapping for any unsecure methods:

    <default-method-access>
       <security-role-mapping name="&lt;default-ejb-caller-role&gt;"
                              impliesAll="true" />
    </default-method-access>

The default role is `<default-ejb-caller-role>` and is defined in the `name` attribute. You can replace this string with any name for the default role. The `impliesAll` attribute indicates whether any security role checking occurs for these methods. This attribute defaults to true, which states that no security role checking occurs for these methods. If you set this attribute to false, the container will check for this default role on these methods.

If the `impliesAll` attribute is set to "`false`", you must map the default role defined in the `name` attribute to a JAZN or XML user or group through the `<user>` and `<group>` elements. The following example shows how all methods not associated with a method permission are mapped to the "`others`" group.

    <default-method-access>
       <security-role-mapping name="default-role" impliesAll="false">
          <group name="others" />
       </security-role-mapping>
    </default-method-access>

#### Specifying Users and Groups by the Client

In order for the client to access methods that are protected by users and groups, the client must provide the correct user or group name with a password that the JAZN or XML user manager recognizes. And the user or group must be the same one as designated in the security role for the intended method.

See Also: "Specifying Credentials in EJB Clients" immediately following

### Specifying Credentials in EJB Clients

When you access EJBs in a remote container, you must pass valid credentials to this container.

- Stand-alone clients define their credentials in the `jndi.properties` file deployed with the EAR file.

- Servlets or JavaBeans running within the container pass their credentials within the `InitialContext`, which is created to look up the remote EJBs.

#### Credentials in JNDI Properties

Indicate the user name (principal) and password (credentials) to use when looking up remote EJBs in the `jndi.properties` file.

For example, if you want to access remote EJBs as `POMGR/welcome`, define the following properties. The `factory.initial` property indicates that you will use the Oracle JNDI implementation:

    java.naming.security.principal=POMGR
    java.naming.security.credentials=welcome
    java.naming.factory.initial=
       oracle.j2ee.server.ApplicationClientInitialContextFactory
    java.naming.provider.url=ormi://myhost/ejbsamples

In your application program, authenticate and access the remote EJBs, as shown in the following example:

    InitialContext ic = new InitialContext();
    CustomerHome =
       (CustomerHome)ic.lookup("java:comp/env/purchaseOrderBean");

#### Credentials in the InitialContext

To access remote EJBs from a servlet or JavaBean, pass the credentials in the `InitialContext` object, as follows:

    Hashtable env = new Hashtable();
    env.put("java.naming.provider.url", "ormi://myhost/ejbsamples");
    env.put("java.naming.factory.initial",
       "oracle.j2ee.server.ApplicationClientInitialContextFactory");
    env.put(Context.SECURITY_PRINCIPAL, "POMGR");
    env.put(Context.SECURITY_CREDENTIALS, "welcome");
    Context ic = new InitialContext (env);
    CustomerHome =
       (CustomerHome)ic.lookup("java:comp/env/purchaseOrderBean")