3.8 J2EE Security Roles
The J2EE authorization model is based on the concept of security roles. Security roles are different from J2EE platform roles. As noted in Section 3.7.2 on page 67, a security role is a semantic grouping of permissions that a given type of application users must be granted to be authorized to use the application. In contrast, a J2EE platform role represents the organizational responsibility in making a J2EE application available to an enterprise, as described in Section 3.7 on page 64. Both declarative and programmatic security are based on the security roles.
Security roles are defined by the Application Component Provider and the Application Assembler. The Deployer then maps each security role to one or more security identities, such as users and groups, in the runtime environment. Listing 3.1 is an example of an XML description of two security roles declared within the deployment descriptor of an application's EAR file.
Listing 3.1. Description of Security Roles Teller and Supervisor
<assembly-descriptor> <security-role> <description> This role is intended for employees who provide services to customers (tellers). </description> <role-name>Teller</role-name> </security-role> <security-role> <description> This role is intended for supervisors. </description> <role-name>Supervisor</role-name> </security-role> </assembly-descriptor>
Declarative authorization can be used to control access to an enterprise bean method. This contract is specified in the deployment descriptor. Enterprise bean methods can be associated with method-permission elements in EJB modules' deployment descriptors. As described in Section 3.7.2 on page 67, a method-permission element specifies one or more EJB methods that are authorized for access by one or more security roles. In Section 3.7.3 on page 70, we observed that the mapping of principals to security roles is performed by the Deployer. If the calling principal is in one of the security roles authorized access to a method, the caller is allowed to execute the method. Conversely, if the calling principal is not a member of any of the roles, the caller is not authorized to execute the method. Listing 3.2 is an example of an XML method-permission element in an EJB module's deployment descriptor.
Listing 3.2. Example of an XML method-permission Element in an EJB Module's Depolyment Descriptor
<method-permission> <role-name>Teller</role-name> <method> <ejb-name>AccountBean</ejb-name> <method-name>getBalance</method-name> </method> <method> <ejb-name>AccountBean</ejb-name> <method-name>getDetails</method-name> </method> </method-permission>
Access to Web resources can be similarly protected. An action on a Web resource URI can be associated with an XML security-constraint element in a Web module's deployment descriptor. The security-constraint element contains one or more URI patterns that can be authorized for access by one or more security roles. If the calling principal is a member of one or more of the security roles authorized to access an HTTP method on a URI, the principal is authorized to access the URI. Conversely, if the calling principal is not a member of any of the roles, the caller is not allowed to access the URI. Listing 3.3 shows a Web module's deployment descriptor fragment that defines access authorization requirements for a Web application.
Listing 3.3. Example of an XML security-constraint Element in a Web Module's Deployment Descriptor
<security-constraint> <web-resource-collection> <web-resource-name> Account servlet protected area </web-resource-name> <url-pattern>/finance/account/</url-pattern> <http-method>GET</http-method> </web-resource-collection> <auth-constraint> <description>Teller can access the URIs</description> <role-name>Teller</role-name> </auth-constraint> </security-constraint>
In a J2EE environment, the security roles form the basis for the security provided by the containers that host the components. A container can provide two types of security: declarative and programmatic.
In the declarative security model, an application expresses its security policies through security constraints in a form external to the application. In J2EE, security constraints are specified in the deployment descriptors. This allows the application to be security-mechanism agnostic, or security unaware. Application code is not required to enable security or enforce the application security policy.
With declarative security, the application's logical security requirements are defined in the deployment descriptors and then mapped by the Deployer and the System Administrator to a deployment environment. The Deployer uses container-deployment tools to process the deployment descriptors. At runtime, the container uses the security policy configured by the Deployer and the System Administrator to enforce authorization.
Declarative security allows greater opportunities for application portability because all the security issues related to the underlying container and operating system are defined in configuration files external to the application. In addition, an application that makes use of declarative security is easier to develop because security and policy configuration issues are managed outside the application. Application developers need not to be security experts, and an application based on declarative security can be more easily extended. Therefore, declarative security should always be used instead of programmatic security unless declarative security alone is insufficient to describe the security requirements of an application.
In the programmatic security model, the application programmer is responsible for explicitly writing the code that defines and enables security. The application security policy is an integral part of the application. An application conforming to this model is said to be security aware.
Programmatic security makes application development more difficult and severely limits the portability and extensibility of an application, because security issues related to the specific application, container, and operating system on which the application is running must be hard-coded. For these reasons, programmatic security should be used only when declarative security alone is insufficient to express the security model of an application. For example, the declarative security capabilities of J2EE V1.3 do not allow expressing a policy whereby a user cannot withdraw more than $1,000 from an automatic teller machine (ATM). Similarly, instance-level authorization to impose that only Bob can access Bob's account cannot be defined declaratively. In these cases, the application needs to enforce these rules programmatically.