| CONTENTS | PREV | NEXT | INDEX | J2EE BluePrints |
Authorization mechanisms limit interactions with resources to collections of users or systems for the purpose of enforcing integrity, confidentiality, or availability constraints. Such mechanisms allow only authentic caller identities to access components. Mechanisms provided by the J2SE platform can be used to control access to code based on identity properties, such as the location and signer of the calling code. In the J2EE distributed component programming model, additional authorization mechanisms are required to limit access to called components based on who is using the calling code. As mentioned in the section on authentication, caller identity can be established by selecting from the set of authentication contexts available to the calling code. Alternatively, the caller may propagate the identity of its caller, select an arbitrary identity, or make the call anonymously.
In all cases, a credential is made available to the called component. The credential contains information describing the caller through its identity attributes. In the case of anonymous callers, a special credential is used. These attributes uniquely identify the caller in the context of the authority that issued the credential. Depending on the type of credential, it may also contain other attributes which define shared authorization properties (for example, group memberships) that distinguish collections of related credentials. The identity attributes and shared authorization attributes appearing in the credential are referred to together as the caller's security attributes. In the J2SE platform, the identity attributes of the code used by the caller may also be included in the caller's security attributes. Access to the called component is determined by comparing the caller's security attributes with those required to access the called component.
In the J2EE architecture, a container serves as an authorization boundary between callers and the components it hosts. The authorization boundary exists inside the container's authentication boundary, so that authorization is considered in the context of successful authentication. For inbound calls, the container compares security attributes from the caller's credential with the access control rules for the target component. If the rules are satisfied, the call is allowed. Otherwise, the call is rejected.
There are two fundamental approaches to defining access control rules: capabilities and permissions. The capabilities approach focuses on what a caller can do. The permissions approach focuses on who can do something. The J2EE application programming model focuses on permissions. In the J2EE architecture, the job of the Deployer is to map the permission model of the application to the capabilities of users in the operational environment.
The container-enforced access control rules associated with a J2EE application are established by the Deployer. The Deployer uses a deployment tool to map an application permission model (typically) supplied by the Application Assembler to policy and mechanisms that are specific to the operational environment. The application permission model is contained in a deployment descriptor.
The deployment descriptor defines logical privileges called security roles and associates them with components to define the privileges required to be granted permission to access components. The Deployer assigns these logical privileges to specific callers to establish the capabilities of users in the runtime environment. Callers are assigned logical privileges based on the values of their security attributes. For example, a Deployer might map a security role to a security group in the operational environment such that any caller whose security attributes indicate that it is a member of the group would be assigned the privilege represented by the role. As another example, a Deployer might map a security role to a list containing one or more principal identities in the operational environment such that a caller authenticated as one of these identities would be assigned the privilege represented by the role.
The EJB container grants permission to access a method only to callers that have at least one of the privileges associated with the method. Security roles also protect Web resource collections, that is, a URL pattern and an associated HTTP method, such as GET. The Web container enforces authorization requirements similar to those for an EJB container. When a resource has no associated security role, permission to access the resource will be granted to all.
In both tiers, access control policy is defined at deployment time, rather than application development. The Deployer can modify the policy provided by the Application Assembler. The Deployer refines the privileges required to access the components, and defines the correspondence between the security attributes presented by callers and the container privileges. In any container, the mapping from security attributes to privileges is scoped to the application, so that the mapping applied to the components of one application may be different from that of another application.
A J2EE container makes access control decisions before dispatching method calls to a component. As a result, the logic or state of a component doesn't affect the access decisions. However, a component can use two methods, EJBContext.isCallerInRole (for use by enterprise bean code) and HttpServletRequest.isUserInRole (for use by Web components), to perform finer-grained access control. A component uses these methods to determine whether a caller has been granted a privilege selected by the component based on the parameters of the call, the internal state of the component, or other factors such as the time of the call.
The Application Component Provider of a component that calls one of these functions must declare the complete set of distinct roleName values used in all of its calls. These declarations appear in the deployment descriptor as security-role-ref elements. Each security-role-ref element links a privilege name embedded in the application as a roleName to a security role. It is ultimately the Deployer who establishes the link between the privilege names embedded in the application and the security roles defined in the deployment descriptor. The link between privilege names and security roles may differ for components in the same application.
There is a trade-off between the external access control policy configured by the Deployer and the internal policy embedded in the application by the Component Provider. The former is more flexible after the application has been written. The latter provides more flexibility, in the form of functionality, while the application is being written. The former is transparent and completely comprehensible. The latter is buried in the application such that it may only be completely understood by the those who developed the application. These trade-offs should be considered in choosing the authorization model for particular components and methods.
When designing the access control rules for protected resources, take care to ensure that the authorization policy is consistently enforced across all the paths by which the resource may be accessed. When method-level access control rules are applied to a component, care must be taken that a less protected method does not serve to undermine the policy enforced by a more rigorously protected method. Such considerations are most significant when component state is shared by disparately protected methods. The simplifying rule of thumb is to apply the same access control rules to all the methods of a component, and to partition an application as necessary to enforce this guideline unless there's some specific need to architect an application otherwise.
When setting an application's access control policy, the Application Component Provider bases policy decisions on assumptions about the call identities selected by the application callers. When a call passes through intermediary components, the caller identity at the destination component may depend on the identity selection decisions made by the intermediaries. The destination component may assume that caller identities have been propagated along the call chain such that the identity of its caller will be that of the caller who initiated the chain. In other cases, the called component must assume that one or more of the callers in its call path will employ an identity selection policy other than identity propagation. The Application Assembler is responsible for communicating these assumptions to the Deployer, while the Deployer configures the caller identity selection for inter-component calls. Unless the Deployer has other instructions from the Application Assembler, they should assume that each caller will propagate the identity of the caller's identity.
The component model of an application may be used to impose authorization boundaries around what might otherwise be unprotected resources. This can be done by using accessor components to implement the authorization barrier. If accessor components are used to create an authorization boundary, access control can either be done externally by the container, or internally by the component, or both.
An accessor component may encapsulate the mapping to an authentication context suitable for interacting with an external resource. Considered in the context of principal mapping for the purpose of authenticating and gaining access to enterprise information system resources, encapsulation for access control can be used to control who is authorized to access a mapping. Depending on the form of the mapping, the authorization rules may be more or less complex. For example, if all access to a resource is performed via a single conceptually omnipotent enterprise information system tier identity, then the J2EE application can implement secure access to the resource by limiting who can access the accessor. If the mapping of authentication context is many-to-many, then the authorization configuration of the accessor may need to define which of a collection of mappings are accessible to the caller, and which should be assumed by default (if the caller does not assert which mapping it requires).
In a typical J2EE application, a client would go through its container to interact with enterprise resources in the Web or EJB tiers. Resources available to the user may be protected or unprotected. Protected resources are distinguished by the presence of authorization rules defined in deployment descriptors that restrict access to some subset of non-anonymous identities. To access a protected resource, a user must present a non-anonymous credential such that its identity can be evaluated against the resource authorization policy. In other words, caller authentication is required any time a caller tries to access a protected component.
9.3.7.1 Controlling Access to Web Resources
To control access to a Web resource, an Application Component Provider or Application
Assembler specifies a security-constraint element with an auth-constraint
subelement in the Web deployment descriptor. Code
Example 9.5 illustrates the definition of a protected resource in a Web
component deployment descriptor. The descriptor specifies that the URL /control/placeorder
can only be accessed by users acting in the role of customer.
<security-constraint> <web-resource-collection> <web-resource-name>placeorder</web-resource-name> <url-pattern>/control/placeorder</url-pattern> <http-method>POST</http-method> <http-method>GET</http-method> </web-resource-collection> <auth-constraint> <role-name>customer</role-name> </auth-constraint> </security-constraint>
| Code Example 9.5 Web Resource Authorization Configuration |
9.3.7.2 Controlling Access to Enterprise Beans
An Application Component Provider or Application Assembler that has defined security roles for an enterprise bean can also specify the methods of the remote and home interface that each security role is allowed to invoke. This is done in the form of method-permission elements. Ultimately, it is the assignment of users to roles that determines if a resource is protected. When the roles required to access the enterprise bean are assigned only to authenticated users, the bean is protected.
Code Example 9.6 contains two styles of method specifications. The first refers to all of the remote and home interface methods of an enterprise bean. The second is used for referring to a specific method of the remote or home interface of an enterprise bean. If there are multiple methods with the same overloaded name, this style refers to all of the overloaded methods. Method specifications can be further qualified with parameter names for methods with an overloaded name.
<method-permission> <role-name>admin</role-name> <method> <ejb-name>TheOrder</ejb-name> <method-name>*</method-name> </method> </method-permission> <method-permission> <role-name>customer</role-name> <method> <ejb-name>TheOrder</ejb-name> <method-name>getDetails</method-name> </method> <method> ... </method-permission>
| Code Example 9.6 Enterprise Bean Authorization Configuration |
9.3.7.3 Unprotected Resources
Many applications feature unprotected Web-tier content, available to any caller without authentication. Some applications also feature unprotected enterprise beans. For example, the sample application (see Section 10.11) allows anonymous, unauthenticated users to access certain EJB resources. In either tier, unprotected resources are characterized by the absence of a requirement that their caller be authenticated. In the Web tier, unrestricted access is provided simply by leaving out an authentication rule. In the EJB tier, unrestricted access is accomplished by mapping at least one role which is permitted access to the resource to the universal set of users independent of authentication.
To understand how each application, and each component within an application can apply its own authorization requirements, consider the following examples.
One application is assembled from two enterprise beans, EJB 1 and EJB 2, each with one method. Each method calls isCallerInRole with the role name MANAGER. The deployment descriptor includes a security-role-ref element for the call to isCallerInRole in each enterprise bean. The security-role-ref for EJB 1 links MANAGER to the role good-managers and the security-role-ref element for EJB 2 links MANAGER to the role bad-managers. The deployment descriptor defines two method-permission elements, one establishes that the role employees can access all methods of EJB 1 and the other does the same for EJB 2. The deployment descriptor has 3 security-role elements: employees, good-managers, and bad-managers. The Deployer assigns User 1 to roles employees and good-managers and assigns User 2 to roles employees and bad-managers.
A second application, with one enterprise bean EJB 3, is also deployed in the container. EJB 3 also makes a call to isCallerInRole with the role name MANAGER. The deployment descriptor for this second application contains a security-role-ref element that links MANAGER to the role good-managers. Similarly, the deployment descriptor defines one method-permission element that establishes that the role employees can access all the methods of EJB 3. The deployment descriptor has 2 role elements, employees and good-managers. The Deployer assigns User 2 to roles employees and good-managers.
Figure 9.4 illustrates the configuration of method permissions as a relationship between roles and methods. It also illustrates the mapping of caller security attributes to roles, and the link between privilege names embedded in the application and roles.
Table 9.1 lists the authorization decisions
that occur when different users initiate method calls on these enterprise beans.
For example, when User 1 initiates a method call on EJB 2's method,
the container dispatches the call because the method-permission
element specifies the security roles employees and good-managers,
and the Deployer has assigned User 1 to the former security role.However,
the isCallerInRole(MANAGER) method returns false, because the security-role-ref
element for EJB 2 links MANAGER to the security role bad-managers,
which is not satisfied for User 1. When User 1 invokes a method on
EJB 3, the call isn't even dispatched, because User 1 isn't
assigned to any security roles.
Figure 9.4 Authorization Scenario