10.5. EJB Component SecurityEJB containers provide fairly rich security capabilities for EJB components that they manage. The following sections discuss transport-level security, authentication, declarative and programmatic authorization, identity propagation, and security best practices for the EJB tier. The material presented here complements the coverage provided in Chapter 6. We'd recommend reviewing the relevant security-related material in that chapter first, then returning to this section for further details. 10.5.1. EJB-Tier Transport-Level SecurityAs discussed in Chapter 6, remote EJB clients can use either RMI/JRMP or CORBA/IIOP protocols to communicate over the network with EJB components. If you need to secure the communications between clients and the EJB container, IIOP traffic can be tunneled over SSL using various IIOP/SSL tunneling protocols. But support for SSL-enabled IIOP is server-specific, so you'll have to ensure that both the EJB container and the client environments support the same secure IIOP protocols. Using secure JRMP connections has been problematic in the past because of a lack of standard implementations of secure JRMP sockets in the Java platform. JDK 1.5 introduced a new standard SSL-enabled RMI socket implementation, but it will likely take some time for these to make their way into EJB container implementations as an option for deployed components. In either case, configuring EJB containers to use secure transport communications is a vendor-specific detail. Consult the documentation for your EJB container for details. 10.5.2. EJB-Tier AuthenticationAs we discussed earlier, clients of EJB components are responsible for authentication of users and for propagating the user's identity to the EJB tier. We already described what happens with a web client, which passes along or propagates credentials from the web application to the EJB. Now, how is authentication handled for a standalone Swing or Standard Widget Toolkit (SWT) application or a command-line application? One option is to use JAAS for authentication. Once the client container authenticates a user in the client tier, the client container passes along the user's identity to the EJB components as shown in Figure 10-6. You leverage JAAS to authenticate the user with various mechanisms such as Kerberos, LDAP, or even the operating system. Figure 10-6. Propagation from client to EJB tier10.5.3. EJB-Tier AuthorizationJ2EE security supports declarative as well as programmatic authorization for the EJB tier as detailed in the following sections. 10.5.3.1. EJB-tier declarative authorizationDeclarative authorization in the EJB tier involves defining authorization policies in your EJB deployment descriptor. These policies specify which roles may access the methods on your EJB components and how these roles are propagated (or not) from the client. Role-based authorizations for accessing EJB methods are set using <method-permission> elements. You can also specify EJB methods that should not be accessed by clients by including them in <exclude-list> elements. The propagation of user roles from the client to the EJB container is controlled using the <security-identity> element with each component's entry in the deployment descriptor. Using a <use-caller-identity> element specifies that any client requests to the EJB component should inherit the identity and roles of the client making the request. If you want all calls to the EJB component to assume a singular role, you can specify a <run-as> element within the <security-identity> element. For details and examples of using these EJB declarative authorization settings, see the section "Deploying EJBs" in Chapter 6. 10.5.3.2. EJB-tier programmatic authorizationThe primary methods that support programmatic authorization in the EJB tier are getCallerPrincipal( ) and isCallerInRole( ) of the javax.ejb.EJBContext interface. getCallerPrincipal( ) returns an instance of java.security.Principal object. What if there is no current authenticated user? The getCallerPrincipal( ) method does not return null; it returns a Principal that represents an unauthenticated identityi.e., an anonymous user. The isCallerInRole( ) method takes a role in string form as shown in Example 10-9. Example 10-9. isCallerInRolepublic static final String VIP_ROLE = "vip_role"; public BigDecimal getPercentageCost( ) { sLogger.info( " in shipping manager bean. get percentage cost : " + mSessionContext.getCallerPrincipal( ).getName( ) ); if (mSessionContext.isCallerInRole(VIP_ROLE)) { return new BigDecimal("3.00"); } return new BigDecimal("7.00"); } Before you pass the role name as an argument to the isCallerInRole( ) method, the role name must be declared in the <security-role-ref> element of the ejb-jar.xml deployment descriptor as shown in Example 10-10. The scope of <security-role-ref> is at the entity bean or session bean level. There is no client caller in case of a message driven bean. Example 10-10. Security role reference<ejb-jar> ... <session> ... <ejb-name>ShippingManager</ejb-name> ... <security-role-ref> <role-name>vip_role</role-name> <role-link>vip</role-link> </security-role-ref> ... </session> ... </ejb-jar> You map the role in the <security-role-ref> element to the <security-role> element using the <role-link> element. The scope of the <security-role> is the entire ejb-jar.xml file and applies to all the enterprise beans in that file. Example 10-11 shows how to specify a <security-role> as part of the <assembly-descriptor>. Example 10-11. Security role in assembly descriptor<ejb-jar> ... <assembly-descriptor> ... <security-role> <description>The VIP role.</description> <role-name>vip</role-name> </security-role> ... </assembly-descriptor> ... </ejb-jar> 10.5.4. EJB Tier Best PracticesWe recommend the following best practices for managing security at the EJB tier:
|