|
|
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 3 of 6
In Lists 4-A and 4-B below, the PortableContext implementations are modified to implement the security methods. Notice that the EJB 1.1 implementation (PortableContext1_1) simply delegates the method requests to the EJB 1.1 EJBContext, while the EJB 1.0 implementation converts requests from the Principal-based model of EJB 1.1 to the Identity model of EJB 1.0.
import javax.ejb.EJBContext;
...
import java.security.Principal;
import java.security.Identity;
public class PortableContext1_0 extends PortableContext {
public Principal getCallerPrincipal( ) { return (Principal)ejbContext.getCallerIdentity( );
}
public boolean isCallerInRole(String roleName){
Identity identity = new RoleIdentity(roleName);
return ejbContext.isCallerInRole(identity);
}
...
}
|
import javax.naming.InitialContext; ... import java.security.Principal; |
The java.security.Identity class implements the java.security.Principal interface, so the getCallerPrincipal( ) method in the PortableContext1_0 class simply casts the Identity object returned from the EJBContext.getCallerIdentity( ) method to its Principal type. This is simple enough; the implementation of the isCallerInRole() method in the PortableContext1_0 class is more complicated, however.
EJB 1.0 required the use of java.security.Identity to verify membership in a security role. As the code in Lists 2-A and 2-B demonstrates, checking a client's role can provide
valuable authorization logic that the access control declarations in the deployment descriptor can't address. Unfortunately,
while the EJB 1.0 specification requires the use of the Identity type as a role identifier, it doesn't specify how a bean should acquire the Identity object specific to the role being tested. The Identity class is an abstract class, so simply instantiating it is not possible. In the examples above, a mysterious RoleIdentity object was instantiated with the name of the role being tested. This provided us with an Identity object that could be used in the isCallerInRole(Identity role) method. But where did the RoleIdentity object come from?
The RoleIdentity class is an extension of the java.security.Identity class, and provides us with a simple, concrete implementation of Identity that we can instantiate with a string name. (A similar RoleIdentity class was originally defined by Jian Lin in a post to the ejb-interest mailing list on September 24, 1999.) Below is the
definition of this class.
import java.security.Identity;
public class RoleIdentity extends Identity {
public RoleIdentity(String name) {
super(name);
}
}
|
Use of the RoleIdentity class works in those EJB servers that limit comparison operations of Identity to the name attribute. In other words, these servers simply compare the string values returned by the getName() methods of the Identity objects.
Some EJB vendors may enlist more complicated mechanisms for comparing the Identity objects. In these cases, you may have to enhance the RoleIdentity defined here, or use a vendor-specific mechanism for verifying membership in a role. BEA's Weblogic Server, for example,
works wonderfully with the RoleIdentity, but it also provides a proprietary mechanism for obtaining group Identity objects (i.e., roles to which identities belong). List 6 shows how the PortableContext1_0.isCallerInRole() method would be coded to use the Weblogic security API instead of RoleIdentity.
public class PortableContext1_0 extends PortableContext {
public boolean isCallerInRole(String roleName){
// Weblogic specific solution
Identity identity = (Identity) weblogic.security.acl.Security.getRealm().getGroup(roleName);
if(identity==null) {
return false;
}
return ejbContext.isCallerInRole(identity);
}
...
}
|
The PortableContext insulates the bean developer from the differences in the security procedures of EJB 1.0 and EJB 1.1. In addition, because
we are using the EJB 1.1 conventions, EJB 1.0 beans will support security in a forward-featured manner. Below is an example
of how a forward-compatible bean would use the security methods defined in the PortableContext.
public class AccountBean implements EntityBean {
int id;
double balance;
String modifiedBy;
EntityContext ejbContext;
PortableContext portableContext;
public void withdraw(Double withdraw)
throws WithdrawLimitException, AccessDeniedException {
// only tellers can withdraw more than 10k
if(withdraw.doubleValue() > 10000) {
boolean isTeller = portableContext.isCallerInRole("teller")
if(!isTeller)
throw new AccessDeniedException( );
}
Double limit = (Double)
portableContext.getEnvironmentEntry(
"java:comp/env/withdraw_limit",Double.class);
if (withdraw.doubleValue() > limit.doubleValue())
throw new WithdrawLimitException(limit);
else
balance = balance - withdraw.doubleValue();
Principal principal = portableContext.getCallerPrincipal( );
String modifiedBy = principal.getName();
}
...
}
|
The PortableContext isn't just able to encapsulate differences between versions of the EJB specification; it can also do so across various brands
of EJB servers. Although all EJB vendors strive for full compliance with the EJB specification, few accomplish this Herculean
task overnight. As a result, servers support the specification in varying degrees, which can make portability between servers
difficult. This problem was exacerbated by the recent introduction of the EJB 1.1 specification. Porting beans between brands
of servers in this climate will be difficult, but many of the brand-to-brand portability problems can be solved easily using
the PortableContext. Concrete implementations of the PortableContext can be created for any brand of EJB server and loaded dynamically at runtime by simply changing the system property java.ejb.portable_context so that it points at the correct implementation class.
Server-side Java: Read the whole series -archived on JavaWorld