Your message has been sent.
This article has been saved to your account.
Go to my account
This article has been emailed to your Kindle.
Send this article
Complete the form below to send this article, EJB 3.1: Controlling Security Programmatically Using JAAS, to a friend (or to yourself). We will never share your details (or your friend's) with anyone. For more information, read our Privacy Policy.
This article by Richard Reese, author of EJB 3.1 Cookbook, covers programmatic EJB security based upon the Java Authentication and Authorization Service (JAAS) API. It should be used when declarative annotation is not adequate to affect the level of security desired. This can occur when access is time-based. For example, a user may only be allowed to access certain services during normal business hours such as when the stock market is open.
| Read more about this book |
(For more resources on EJB, see here.)
The reader is advised to refer the initial two recipies from the previous article on the process of handling security using annotations.
Getting ready
Programmatic security is affected by adding code within methods to determine who the caller is and then allowing certain actions to be performed based on their capabilities. There are two EJBContext interface methods available to support this type of security: getCallerPrincipal and isCallerInRole. The SessionContext object implements the EJBContext interface. The SessionContext's getCallerPrincipal method returns a Principal object which can be used to get the name or other attributes of the user. The isCallerInRole method takes a string representing a role and returns a Boolean value indicating whether the caller of the method is a member of the role or not.
The steps for controlling security programmatically involve:
- Injecting a SessionContext instance
- Using either of the above two methods to effect security
How to do it...
To demonstrate these two methods we will modify the SecurityServlet to use the VoucherManager's approve method and then augment the approve method with code using these methods.
First modify the SecurityServlet try block to use the following code. We create a voucher as usual and then follow with a call to the submit and approve methods.
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet SecurityServlet</title>");
out.println("</head>");
out.println("<body>");
voucherManager.createVoucher("Susan Billings", "SanFrancisco",
BigDecimal.valueOf(2150.75));
voucherManager.submit();
boolean voucherApproved = voucherManager.approve();
if(voucherApproved) {
out.println("<h3>Voucher was approved</h3>");
} else {
out.println("<h3>Voucher was not approved</h3>");
}
out.println("<h3>Voucher name: " + voucherManager.getName() +
"</h3>");
out.println("</body>");
out.println("</html>");
Next, modify the VoucherManager EJB by injecting a SessionContext object using the @Resource annotation.
public class VoucherManager {
...
@Resource
private SessionContext sessionContext;
Let's look at the getCallerPrincipal method first. This method returns a Principal object (java.security.Principal) which has only one method of immediate interest: getName. This method returns the name of the principal.
Modify the approve method so it uses the SessionContext object to get the Principal and then determines if the name of the principal is "mary" or not. If it is, then approve the voucher.
public boolean approve() {
Principal principal = sessionContext.getCallerPrincipal();
System.out.println("Principal: " + principal.getName());
if("mary".equals(principal.getName())) {
voucher.setApproved(true);
System.out.println("approve method returned true");
return true;
} else {
System.out.println("approve method returned false");
return false;
}
}
Execute the SecurityApplication using "mary" as the user. The application should approve the voucher with the output as shown in the following screenshot:

Execute the application again with a user of "sally". This execution will result in an exception.
INFO: Access exception
The getCallerPrincipal method simply returns the principal. This frequently results in the need to explicitly include the name of a user in code. The hard coding of user names is not recommended. Checking against each individual user can be time consuming. It is more efficient to check to see if a user is in a role.
The isCallerInRole method allows us to determine whether the user is in a particular role or not. It returns a Boolean value indicating whether the user is in the role specified by the method's string argument. Rewrite the approve method to call the isCallerInRole method and pass the string "manager" to it. If the return value returns true, approve the voucher.
public boolean approve() {
if(sessionContext.isCallerInRole("manager")) {
voucher.setApproved(true);
System.out.println("approve method returned true");
return true;
} else {
System.out.println("approve method returned false");
return false;
}
}
Execute the application using both "mary" and "sally". The results of the application should be the same as the previous example where the getCallerPrincipal method was used.
How it works...
The SessionContext class was used to obtain either a Principal object or to determine whether a user was in a particular role or not. This required the injection of a SessionContext instance and adding code to determine if the user was permitted to perform certain actions.
This approach resulted in more code than the declarative approach. However, it provided more flexibility in controlling access to the application. These techniques provided the developer with choices as to how to best meet the needs of the application.
There's more...
It is possible to take different actions depending on the user's role using the isCallerInRole method. Let's assume we are using programmatic security with multiple roles.
@DeclareRoles ({"employee", "manager","auditor"})
We can use a validateAllowance method to accept a travel allowance amount and determine whether it is appropriate based on the role of the user.
public boolean validateAllowance(BigDecimal allowance) {
if(sessionContext.isCallerInRole("manager")) {
if(allowance.compareTo(BigDecimal.valueOf(2500)) <= 0) {
return true;
} else {
return false;
}
} else if(sessionContext.isCallerInRole("employee")) {
if(allowance.compareTo(BigDecimal.valueOf(1500)) <= 0) {
return true;
} else {
return false;
}
} else if(sessionContext.isCallerInRole("auditor")) {
if(allowance.compareTo(BigDecimal.valueOf(1000)) <= 0) {
return true;
} else {
return false;
}
} else {
return false;
}
}
The compareTo method compares two BigDecimal values and returns one of three values:
- -1 – If the first number is less than the second number
- 0 – If the first and second numbers are equal
- 1 – If the first number is greater than the second number
The valueOf static method converts a number to a BigDecimal value. The value is then compared to allowance.
Summary
This article covered programmatic EJB security based upon the Java Authentication and Authorization Service (JAAS) API.
Further resources on this subject:
- EJB 3.1: Introduction to Interceptors [Article]
- EJB 3.1: Working with Interceptors [Article]
- Hands-on Tutorial on EJB 3.1 Security [Article]
- EJB 3 Entities [Article]
- Developing an EJB 3.0 entity in WebLogic Server [Article]
- Building an EJB 3.0 Persistence Model with Oracle JDeveloper [Article]
- NetBeans IDE 7: Building an EJB Application [Article]
About the Author :
Richard M. Reese
Richard M. Reese holds a Ph.D. in Computer Science from Texas A & M University and is currently an Associate Professor in the Department of Engineering and Physics at Tarleton State University in Stephenville, Texas. In addition to his experience in academia, Richard has over 17 years experience in industry including operating system development at GTE Automatic Electric Labs and at Lockheed Martin in Fort Worth, Texas, where he supervised a tool development group and oversaw various research and development projects. Prior to his industrial experience he served four years in the United States Air Force.
Richard has been involved with Java since 1996 and is a certified Java SE 7 Associate Programmer. He has worked as consultant/instructor of software languages in private and public classes providing him with a variety of insight into industry applications. He has published numerous papers and has developed courseware for a variety of topics including advanced Java technologies. He has also written the EJB 3.1 Cookbook and Java 7 New Features Cookbook for Packt Publishing.
Books From Packt
|
|



Post new comment