EJB 3.1: Controlling Security Programmatically Using JAAS

Exclusive offer: get 50% off this eBook here
EJB 3.1 Cookbook

EJB 3.1 Cookbook — Save 50%

Enterprise JavaBean 3.1 - Build real world EJB solutions with a collection of simple but incredibly effective recipes with this book and eBook

$32.99    $16.50
by Richard M. Reese | June 2011 | Cookbooks Enterprise Articles Java

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.

 

EJB 3.1 Cookbook

EJB 3.1 Cookbook

Build real world EJB solutions with a collection of simple but incredibly effective recipes

        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:

  1. Injecting a SessionContext instance
  2. 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:

EJB 3.1: Controlling Security Programmatically Using JAAS

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 Cookbook Enterprise JavaBean 3.1 - Build real world EJB solutions with a collection of simple but incredibly effective recipes with this book and eBook
Published: June 2011
eBook Price: $32.99
Book Price: $54.99
See more
Select your format and quantity:

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


Java EE 6 with GlassFish 3 Application Server
Java EE 6 with GlassFish 3 Application Server

NetBeans IDE 7 Cookbook
NetBeans IDE 7 Cookbook

EJB 3 Developer Guide
EJB 3 Developer Guide

Java EE 5 Development with NetBeans 6
Java EE 5 Development with NetBeans 6

GlassFish Security
GlassFish Security

GlassFish Administration
GlassFish Administration

JBoss AS 5 Development
JBoss AS 5 Development

EJB 3.0 Database Persistence with Oracle Fusion Middleware 11g
EJB 3.0 Database Persistence with Oracle Fusion Middleware 11g


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software