Designing Secure Java EE Applications in GlassFish

Exclusive offer: get 50% off this eBook here
GlassFish Security

GlassFish Security — Save 50%

Secure your GlassFish installation, Web applications, EJB applications, Application Client modules, and Web services

$26.99    $13.50
by Masoud Kalali | May 2010 | Java Open Source

In this article series by Masoud Kalali, author of GlassFish Security, we are going to develop a secure Java EE application with all standard modules including Web, EJB, and application client modules.

Security is an orthogonal concern for an application and we should assess it right from the start by reviewing the analysis we receive from business and functional analysts. Assessing the security requirements results in understanding the functionalities we need to include in our architecture to deliver a secure application covering the necessary requirements.

Security necessities can include a wide area of requirements, which may vary from a simple authentication to several sub-systems. A list of these sub-systems includes identity and access management system and transport security, which can include encrypting data as well.

In this article series, we will develop a secure Java EE application based on Java EE and GlassFish capabilities. In course of the article, we will cover the following topics:

  • Analyzing Java EE application security requirements
  • Including security requirements in Java EE application design
  • Developing secure Business layer using EJBs
  • Developing secure Presentation layer using JSP and Servlets
  • Configuring deployment descriptors of Java EE applications
  • Specifying security realm for enterprise applications
  • Developing secure application client module
  • Configuring Application Client Container

Developing Secure Java EE Applications in GlassFish is the second part of this article series.

Understanding the sample application

The sample application that we are going to develop, converts different length measurement units into each other. Our application converts meter to centimeter, millimeter, and inch. The application also stores usage statistics for later use cases.

Guest users who prefer not to log in can only use meter to centimeter conversion, while any company employee can use meter to centimeter and meter to millimeter conversion, and finally any of company's managers can access meter to inch in addition to two other conversion functionalities. We should show a custom login page to comply with site-wide look and feel.

No encryption is required for communication between clients and our application but we need to make sure that no one can intercept and steal the username and passwords provided by members. All members' identification information is stored in the company's wide directory server.

The following diagram shows the high-level functionality of the sample application:

We have login action and three conversion actions. Users can access some of them after logging in and some of them can be accessed without logging in.

GlassFish Security Secure your GlassFish installation, Web applications, EJB applications, Application Client modules, and Web services
Published: May 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Analyzing sample application business logic

Before looking at security requirements and factors affecting the software security let's see what we need to provide in our business layer. Our business logic consists of conversion operations and persistence of the conversion operations usage statistics. We can use a stateless Session Bean with three methods, one for each type of conversion. And for statistics persistence we can use EJB 3 entity beans.

After studying the application description we can extract the following security-related requirements which we need to address to comply with the application description:

  • Authentication is required
  • Authentication should happen over a secure channel
  • Authorization is required
  • We need to use LDAP security realm

So far we translated the business analysis to technical requirements and now we are going to check each requirement in further detail to extract the implementation details. For implementing the sample application we can use a simple bottom-up procedure.

The following diagram shows the application blocks down to JSP files, Servlet, and EJBs.

As you can see we have Web module, EJB module, and an application client module. The Web module and the application client module presents a frontend for the EJB layer that performs both business logic, which is the conversion operations, and storing the conversion operation invocation statistics using Entity Beans. GlassFish uses the LDAP realm to authenticate the users against the specified directory server.

Implementing the Business and Persistence layers

The Persistence layer consists of an Entity Bean named Visit; we use this entity bean to store information about each visit. We will use a session bean with three business methods to convert a given length in meter to centimeter, millimeter, and inch.

Implementing the Persistence layer

We are using EJB 3 to develop the Persistence layer so we will only need to implement the entity bean and define the persistence unit. The following listing shows the Visit class.

@Entity
public class Visit implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Temporal(javax.persistence.TemporalType.DATE)
private Date visitDate;
private String username;
private String operationName;
private int conversionValue;
public Visit() {
}

public Visit(Date visitDate, String username, String Operation,
int conversionValue) {
this.visitDate = visitDate;
this.username = username;
this.operationName = Operation;
this.conversionValue = conversionValue;
}
}

Now that our entity bean is ready we can start looking at our session bean that drives the application business logic and also stores information about each invocation using the Visit entity bean. The following listing shows Conversion session bean local interface.

@Local
public interface ConversionLocal {
float toInch(int meter);
int toCentimeter(int meter);
int toMilimeter(int meter);
}

All of these methods are implemented in Conversion bean implementation which is as follows:

@Stateless
public class ConversionBean implements ConversionLocal {
@PersistenceContext(unitName = "chapter3")
private EntityManager em;
@Resource
private SessionContext ctx;

@RolesAllowed({"manager_role"})
public float toInch(int meter) {
persist(meter, "toInch");
return Math.round(meter * 39.37);
}

@PermitAll
public int toCentimeter(int meter) {
persist(meter, "toCentimeter");
return meter * 100;
}

@RolesAllowed("employee_role")
public int toMilimeter(int meter) {
persist(meter, "toInch");
return meter * 1000;
}

private void persist(int value, String operationName) {
String userName = ctx.getCallerPrincipal().getName();
Visit v = new Visit(new Date(), userName, operationName, value);
em.persist(v);
}
}

Starting from the first line we are using @Stateless to mark this class as a stateless Session Bean. Later on we are using @PersistenceContext to inject an entity manager into the instance. We will use this entity manager to store Visit entities. Then we are using @Resource to inject the current SessionContext into the session bean. Later on we will use it to extract the current principal and username of the invoker. The first security-related annotation is @RolesAllowed({"manager"}), which instructs the application server to only permit an authenticated user with manager role to invoke this method. After this we have @PermitAll which instructs the application server to allow anyone, either authenticated or not, to invoke this method. And finally we are using @RolesAllowed("employee") to instruct the application server that any authenticated user with employee role can invoke this method.

The persist method stores the invocation information. This information includes the current invoker username, which we extract from SessionContext using the getCallerPrincipal().getName() method.

Finally we have a persistence unit that uses sample data source and sample database which is bundled with GlassFish. The listing shown below contains a snippet of persistence.xml file, which configures a persistence unit.

<persistence-unit name="chapter3" transaction-type="JTA">
<provider>oracle.toplink.essentials.PersistenceProvider
</provider>
<jta-data-source>jdbc/sample</jta-data-source>
<class>book.glassfish.security.chapter3.Visit</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<properties>
<property name="toplink.ddl-generation" value="create-tables"/>
</properties>
</persistence-unit>

Now that we have our Persistence and Business layers ready we can start looking at the Web layer and how the Web layer can complement the inner layer in securing the system.

 

GlassFish Security Secure your GlassFish installation, Web applications, EJB applications, Application Client modules, and Web services
Published: May 2010
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

Deploying the application client module in the Application Client Container

The application client module can be a first layer Java SE application which directly communicates with the EJB container and uses services like transaction and security management of EJB container through the Application Client Container.

When it comes to software structure an application client is not different from a simple Java SE application. It has a main method, which is the software entry point and we can access different Java EE services simply with annotation or using deployment descriptors.

The following listing shows the main method for our application client, which invokes the Conversion Session Bean and prints the result.

public class Main {

@EJB
private static ConversionRemote conversionBean;
public static void main(String[] args) {
System.out.println(conversionBean.toInch(10));
}
}

You may ask how this application can use injection and access an EJB instance. The secret is, hiding in another type of container called the Application Client Container. We deploy an application client module in the ACC and later execute it in the machine either as Java Web Start application or simply using GlassFish-provided scripts. When we run this application the following procedure takes place:

  1. Application client (launched using Web Start or directly) results in the ACC trying to inject the secured EJB.
  2. The EJB method requires authentication, so GlassFish calls the default CallbackHandler to get user login.
  3. The default CallbackHandler, which is a simple username and password collecting dialog, appears on the client's screen.
  4. The collected username and password are sent back to application server for authentication and authorization.
  5. After a successful authentication, the method invocation goes through.

This procedure happens even if we do not add any single line of configuration to our EJB module deployment descriptor or Application Client deployment descriptor. The following figure shows more detail about the interaction between different modules when a secure EJB is called from an application client.

The default configuration for application client authentication is summarized in the following table:



Security Measure

Description

Security Realm

If no realm specified in sun-application.xml EJB container will use GlassFish default security realm. Default realm is file realm if not configured otherwise.

Authentication CallbackHandler

Default CallbackHandler is a simple swing dialog, which collects username and password.

Transport security

No encryption is applied on data transportation

All of these measures are configurable either through the Application Client deployment descriptor or the EJB deployment descriptor or the ACC deployment descriptor. The following table shows which attributes are configurable through each one of these deployment descriptors.



Attribute

Deployment descriptor

Authentication mechanism

sun-ejb-jar.xml

Security Realm

sun-acc.xml and sun-ejb-jar.xml

SSL and transport security

sun-acc.xml and sun-ejb-jar.xml

Callbackhandler<!-- --> to collect username and password

application-client.xml

Two of the deployment descriptors included in the above table are specific to each vendor and may differ between different application servers. The only standard descriptor is application-client.xml, which is a part of the application client standard. This descriptor is placed inside the META-INF directory of the client application and contains information like which resources our application is using, how the application is accessing these resources, and finally definitions of the callback handler we want to use to collect user credentials.

The following figure shows default the CallbackHandler, which is fired to collect username and password before the container lets the application invoke a method with security constraint.

We can change the default CallbackHandler in application-client.xml by specifying a new Callbackhandler. The new callback should implement the javax.security.auth.callback.CallbackHandler. The following snippet shows the callback-handler element in application-client.xml.

<callback-handler>
book.glassfish.security.chapter1.SwingCallbackHandler
</callback-handler>

We can use a programmatic way to provide the ACC with username and password instead of using the callback mechanism to have more control over the authentication procedures. To conduct programmatic login we can use com.sun.appserv.security.ProgrammaticLogin class to login before we access any EJB method which has security constraints, defining security measures for communication over IIOP.

We can use the GlassFish-specific deployment descriptor for EJB modules to define several types of configuration elements. We can use one set of these elements to define security measures for communication between the EJB container and the clients over IIOP (Internet Inter-Orb Protocol).

The super element for the IOR security is ior-security-config, which includes the following sub elements:

  • The transport-config for specifying transport security
  • The sas-context for specifying the caller propagation options
  • The as-context for specifying the authentication method, the security realm we want to use for authentication.

Following snippet shows what we should include in the EJB deployment descriptor to get SSL transport security along with username and password-based authentication using the LDAPRealm.

<ior-security-config>
<transport-config>
<integrity>required</integrity>
<confidentiality>required</confidentiality>
<establish-trust-in-target>Required
</establish-trust-in-target>
<establish-trust-in-client>none</establish-trust-in-client>
</transport-config>
<as-context>
<auth-method>username_password</auth-method>
<realm>LDAPRealm</realm>
<required>true</required>
</as-context>
<sas-context>
<caller-propagation>supported</caller-propagation>
</sas-context>
</ior-security-config>

Starting from the top, this snippet instructs the EJB container's IIOP listener to use SSL for data transmission to ensure the integrity and confidentiality of data which is transferred between client and server. Other possible values for integrity and confidentiality elements are Supported and None, which means server supports SSL if requested by clients or it does not provide them even if the client asks for data integrity and confidentiality.

We can have SSL mutual authentication by changing the value of establish-trust-in-target and establish-trust-in-client to required. This way the client will authenticate itself to the server using its digital certificate and in the same way the server will authenticate itself to the client using the digital certificate we specified for IIOP listeners.

When using mutual authentication, we should ensure that the trust store of the client trusts the certificate of the server and the trust store of the server trusts the certificate of the client. To achieve this we should:

  1. Add the digital certificate of the client's certificate issuer to the server trust store.
  2. Include the digital certificate of the server's certificate issuer to the client's trust store.

Later in the code snippet we have the as-context element that we can use to specify which authentication method and security realm we want to use for authenticating clients that need to invoke a secure method of an EJB. The only supported authentication method is USERNAME_PASSWORD.

The last element is sas-context. We can use it to specify whether EJB container accepts propagated caller identities or not. Possible values are Supported, Required, and None.

Configuring Application Client Container security

The Application Client Container hosts a Java SE layer application that interacts with the EJB container of the application server using IIOP. Each instance of the container can only host one instance of the client application and can be configured for that client application instance.

The sun-acc.xml structure follows the schema defined in the http://www.sun.com/software/appserver/dtds/sun-application-client-container_1_2.dtd and allows us to configure every aspect of the ACC. The following shows the content of sun-acc.xml, which has both authentication and transport security configured.

<client-container>
<target-server name="localhost" address="127.0.0.1" port="3700">
<security>
<ssl cert-nickname="s1as"
ssl2-enabled="false"
ssl2-ciphers="-rc4,-rc4export,-rc2,-rc2export,-des,
-desede3"
ssl3-enabled="true"
ssl3-tls-ciphers="+rsa_rc4_128_md5,
-rsa_rc4_40_md5,+rsa3_des_sha,+rsa_des_sha,
-rsa_rc2_40 _md5,-rsa_null_md5,-rsa_des_56_sha,
-rsa_rc4_56_sha"
tls-enabled="true"
tls-rollback-enabled="true"/>
<cert-db path="ignored" password="ignored"/>
<!-- not used -->
</security>
<auth-realm name="LDAPRealm"
classname="com.sun.enterprise.security.auth.realm.ldap.LDAPRealm">
<property name="directory"
value="ldap://127.0.0.1:1389 "/>
<property name="base-dn" value=" dc=example,dc=com "/>
<property name="search-bind-password" value="123456"/>
<property name="jaas-context" value="ldapRealm"/>
</auth-realm>
</target-server>
<client-credential user-name="james" password="james"/>
</client-container>

Starting from the top, we are instructing the container to use a certificate identified by client nickname. Later on we will see how we can specify which keystore and trust store we want our client container to use when we launch our application.

All other properties of the ssl element specify which SSL version and cipher suites are available to the ACC to choose from. During the negotiation between server and client to establish an SSL session, the strongest cipher suite supported by both server and client is selected.

In addition to configuring the transport security we can configure the authentication mechanism for ACC in order to let ACC collect the identification information and send them back to server when required. Following the security element we have the auth-realm element which specifies the authentication realm that ACC must use to conduct the authentication.

The one thing that you should remember is the fact that this configuration has nothing to do with the LDAP realm we configured in the server. This configuration affects only the client container instance running in the client machine and using this particular sun-acc.xml file.

Next we have the client-credential element which we can use to specify the default client credential that ACC sends to server instead of collecting the username and password. This element ensures that a single principal is used for all invocation without end users knowing about it.

Using SSL always bring out the issue of keystore and trust store which the application requires using during the SSL handshake and SSL session. There is no vendor-specific way to pass the trust and key store information to Java runtime and rather we can use the JVM environment variables to set these values.

When JVM starts and needs to use SSL, it looks for some environment variables to initiate the SSL session. These variables are included in the following table.



Variable

Description

javax.net.ssl.keyStore

Path to keystore containing the client certificate.

javax.net.ssl.trustStore

Path to trust store containing certificate issuer's certificates.

javax.net.ssl.keyStorePassword

The keystore password.

javax.net.ssl.trustStorePassword

The trust store password.

In Linux, we can use the following command to export these variables before launching the application client using the appclient script.

export VMARGS="-Djavax.net.ssl.keyStore=key-store-path -Djavax.net.ssl.trustStore=
trust-store-path -Djavax.net.ssl.keyStorePassword=key-store-password -Djavax.net.ssl.trustStorePassword=trust-store-password"

For Microsoft Windows we can use the set command to set VMARGS value as follows:

set VMARGS="-Djavax.net.ssl.keyStore=key-store-path -Djavax.net.ssl.trustStore=
trust-store-path -Djavax.net.ssl.keyStorePassword=key-store-password -Djavax.net.ssl.trustStorePassword=trust-store-password"

To create a working pair of certification stores we can follow the same steps we followed to create keystore and trust store for GlassFish application server. Using the same certificate issuer will guarantee that GlassFish will accept the certificate provided by the client and the client will accept the certificate provided by GlassFish.

Now that we have set the required runtime arguments for JVM we can run the client application and be assured about data confidentiality and integrity. The sample application for this article is included in the source code archive of the book.

Read Developing Secure Java EE Applications in GlassFish here.

 

About the Author :


Masoud Kalali

Masoud Kalali has been working on software development projects since 1998, which gives him a broad perspective on software development in general and changes in the software development landscape in the past 1.5 decades. Masoud has experience with a variety of technologies (.NET, J2EE, CORBA, and COM+) on diverse platforms (Solaris, Linux, and Windows). He has a masters degree in Information Systems with a bachelor degree in Software Engineering.

Masoud has authored a fair number of articles and other types of material, including several articles at Java.net and Dzone. He is the author of multiple refcardz, published by Dzone, including but not limited to Using XML in Java (http://refcardz.dzone.com/refcardz/using-xml-java) and Security and GlassFish v3 (http://refcardz.dzone.com/refcardz/getting-startedglassfish) refcardz. Masoud is one of the founding members of NetBeans Dream Team (http://wiki.netbeans.org/NetBeansDreamTeam) and a GlassFish community spotlighted developer (https://glassfish.java.net/public/developers.html). Masoud is the author of GlassFish Security (http://www.packtpub.com/glassfish-security/book) that was published in 2010, covering GlassFish v3 security and Java EE 6 security.

Masoud's main area of research and interest includes service-oriented architecture and large-scale systems development and deployment. In his spare time he enjoys photography, mountaineering, and climbing.

Masoud's Twitter handle is @MasoudKalali if you want to know what he is up to.

Books From Packt

Pentaho 3.2 Data Integration: Beginner's Guide
Pentaho 3.2 Data Integration: Beginner's Guide

WordPress and Flash 10x Cookbook
WordPress and Flash 10x Cookbook

Spring Python 1.1
Spring Python 1.1

Drupal E-commerce with Ubercart 2.x
Drupal E-commerce with Ubercart 2.x

Learning jQuery 1.3
Learning jQuery 1.3

OpenStreetMap
OpenStreetMap

Firebug 1.5: Editing, Debugging, and Monitoring Web Pages
Firebug 1.5: Editing, Debugging, and Monitoring Web Pages

Getting started with Audacity 1.3
Getting started with Audacity 1.3

Your rating: None Average: 5 (1 vote)

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
c
F
i
K
K
N
Enter the code without spaces and pay attention to upper/lower case.
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