Create an anonymous authentication module

Use a CAPTCHA-based authentication module for J2EE Web applications

The Web application landscape is constantly evolving. What started off as a simple means of sharing documents and information has quickly evolved into a platform for conducting business. Authentication and authorization are critical features for these applications. The landscape has evolved again, and we have returned to community-oriented applications like blogs and wikis. Since authors solicit comments and reader feedback, authentication is not the most critical feature for these applications. In some cases, the fear of identification deters potential contributors. The absence of authentication, however, results in its own set of problems: spam. Sample a few messages found on the Web:

  • "I suppose wiki spam is inevitable. I've set up the wiki part of this site to be fairly open to changes to encourage readers and visitors to interact, but now for the second time a spammer has dropped a bunch of links to some Chinese Websites onto the pages." From X-Pollen.
  • "Note to all wiki spammers: As of 1-2-2005 no changes to this wiki, either by editing or adding new pages, will be picked up by search engines until 10 hours have passed. All spam on this site is usually deleted in minutes, an hour at the most, so it is now pointless to try to add spam of any type to this wiki." From C2 Wiki.

Clearly, spam must be addressed. Most of these malicious attacks happen when the spam-bots are able to figure out data submission patterns. One option for stopping such attacks is to present a challenge that can only be passed by humans and not computers. Enter Turing tests. Named after the famous scientist Alan Turing, these tests determine the capability of machines to perform human-like operations. One of the most famous styles is CAPTCHA(an acronym for completely automated public Turing test to tell computers and humans apart). CAPTCHAs frequently appear as images of fuzzy or distorted letters and numbers that humans can read and respond to, but automated optical-character-recognition software have trouble identifying.

Figure 1 shows a typical CAPTCHA.

Figure 1. A sample CAPTCHA

Already, most of the major service providers (Yahoo, Hotmail, Google) are using CAPTCHAs on their free applications, which, to some extent, help them fight spam and fake registrations. In this article, we explore a method for adding CAPTCHA-based authentication to our own Web applications.

First, let's quickly look at the J2EE Web application security model.

J2EE security model

Security has been one of the focus areas guiding Java's development. Needless to say, J2EE has adopted the same principles and provides a robust framework for building secure applications. Security in J2EE applications is a vast topic that I can't cover in detail here. Several excellent resources cover this topic in detail. I strongly recommend that teams and developers spend time familiarizing themselves with these concepts. For this article, I present a 20,000-foot view of some of the key concepts.

Key concepts

Security in J2EE applications can be enforced by using either a declarative approachor a programmatic approach.

As the name suggests, when using the declarative approach, an application developer defines an application's security constraints outside the application code. These declarations are made in deployment descriptors (web.xml, ejb-jar.xml), and the container's runtime environment guarantees their enforcement. Declarative security allows developers to:

  • Restrict access to resources only to principals with given roles (e.g., "/admin/*" is restricted to the "administrator" role)
  • Restrict access to URLs only on certain protocols (e.g., "/customer/*" is only accessible via HTTPS)
  • Restrict access to servlets only to principals with given roles (e.g., SiteShutdownServlet is restricted to the "god" role)
  • Restrict individual methods on EJB (Enterprise JavaBeans) components only to principals with given roles (e.g., PurchasingEJBis restricted to the "customer" role)
  • Automatically redirect users to login page when they request a restricted resource, but have not yet logged into the system

On the other hand, the programmatic approach provides mechanisms for calling and querying the security infrastructure. The developer must enforce these constraints. The programmatic approach helps to:

  • Retrieve the principal associated with the current authenticated user: HttpServletRequest.getUserPrincipalor EJBContext.getCallerPrincipal
  • Query if the user has been assigned a specific role: HttpServletRequest.isUserInRole(String role)or EJBContext.isCallerInRole(String role)

Both these approaches have their own limitations and hence complement each other.

Declarative security for Web applications

Declarative security for Web applications is passive in nature. This means that only on initial access to the protected resource by an unauthenticated client, is the user forwarded to the login page. If the user is already authenticated and has the necessary authorization (role), he or she is allowed to access the resource.

One of the most common approaches to declarative security in Web applications is to use form-based authentication. The Web application deployment descriptor web.xml declares all the necessary elements required for such configuration in two sections.

The first section is common to the entire Web application. It identifies:

  • The login method that needs to be used (auth-method). J2EE supports the following authentication mechanisms BASIC, DIGEST, FORM, or CERT.
  • The login and error page for form-based authentication (form-login-config).
  • Superset of all roles that can be used in the application (security-role).

Figure 2 shows the key elements of the first section and their relationships.

Figure 2. Application-wide security configuration. Click on thumbnail to view full-sized image.

The second section identifies resource-specific constraints. The deployment descriptor can contain zero or more of the following declarations:

  • The section of the site that needs to be protected. This is configured using the url-pattern element within web-resource-collection.
  • The roles that have permission to access this resource (auth-constraint). These roles are generally a subset of roles declared in the first section.
  • The transport guarantees associated with accessing a resource (user-data-constraint).

Figure 3 shows the second section's key elements and their relationships.

Figure 3. Resource-specific security configuration. Click on thumbnail to view full-sized image.

Let's walk through a sample web.xml:

                    

<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN" "http://java.sun.com/J2EE/dtds/web-app_2_2.dtd">

< web-app>

< !-- ... -->

< !-- Define the security constraint. This will limit the /admin/* portion of the application to only be accessible to users within the "admin" role. When an unauthenticated user attempts to access this section of the site, they will be automatically presented with the login page. --> <security-constraint>

< !-- Define the context-relative URL(s) to be protected --> <web-resource-collection> <web-resource-name>Protected Area</web-resource-name> <url-pattern>/admin/*</url-pattern> <http-method>GET</http-method> <http-method>POST</http-method> </web-resource-collection>

< !-- Define the roles that are allowed to access this URL with the given methods --> <auth-constraint> <role-name>admin</role-name> </auth-constraint>

< !-- Transport guarantee could be used to guarantee an HTTPS protocol --> <user-data-constraint> <transport-guarantee>NONE</transport-guarantee> </user-data-constraint>

< /security-constraint>

< !-- Define the method for authenticating a user when requesting a restricted page. Methods include BASIC (the simple pop-up dialog), FORM and CERTIFICATE. --> <login-config> <!-- We will use form based authentication --> <auth-method>FORM</auth-method> <realm-name>Default Realm</realm-name>

< !-- where should the user be forwarded to enter his credentials --> <form-login-config> <form-login-page>/login/login.jsp</form-login-page> <!-- On error the user will be shows this page It can also server side forward back to the login page, which is popular behavior for most sites. --> <form-error-page>/login/error.jsp</form-error-page> </form-login-config> </login-config>

< !-- Finally a list of all security roles in the application must be given. --> <security-role> <description>Capable of administrating the site</description> <role-name>admin</role-name> </security-role> </web-app>

The sample deployment descriptor contains the following security configuration:

  • Restrict access to URLs that begin with the pattern /admin/*(url-pattern)
  • The resources under /admin can only be accessed using HTTP GET or POST (http-method)
  • The resources can be served over a normal HTTP connection (transport-guarantee)
  • Only users belonging to the "admin" role can access these resources (role-name)
  • Remote users are authenticated using form-based authentication (auth-method)
  • The users will be shown a login page—/login/login.jsp—for entering credentials (form-login-page)
  • If any errors occur during authentication, users will be shown an error page—/login/error.jsp (form-error-page)

So far, I have covered the key concepts of the J2EE security model. Let's now look at ways to extend a container's security infrastructure.

1 2 3 Page 1
Page 1 of 3