ONJava.com    
 Published on ONJava.com (http://www.onjava.com/)
 See this if you're having trouble printing code examples


Web FORM-Based Authentication

by Dion Almaer
08/06/2001

In this article, we will walk through the various security settings that we can set up in the Web Application framework, going into detail on how you can set up FORM-based authentication.

All of the code from this article should work with any Web container that supports the Servlet 2.2 API and above. This article assumes that you have knowledge of Web applications, servlets, and JSP's.

We will walk through the following items:

Configuring security on a resource

To secure a resource we will:

Step One: Restrict resources based on a given URL pattern

First of all, we want to protect some resource in our Web container. We restrict an area of our site based on a URL pattern. So, let's restrict access to any URL that starts with /secure.

All of our configuration will take place in a file named web.xml that lives in the magical directory WEB-INF. This conforms to the Web Application standard defined by Sun (and company). In your web.xml file you will tell the Web container that you want to restrict an area based on the URL pattern, which will look like:

<security-constraint>
<web-resource-collection>
  <web-resource-name>SecurePages</web-resource-name>
  <description>Security constraint /secure</description>
  <url-pattern>/secure/*</url-pattern>
  <http-method>POST</http-method>
  <http-method>GET</http-method>
</web-resource-collection>

The interesting tags here are:

Step Two: Name the security roles that are allowed access to the resources

Now we have defined the area that we are securing, and what HTTP methods we will allow. We still need to tell the container who has access to this given resource. To do this we set up abstract security "roles" for our entire Web application, and list the roles that have access to each <security-constraint>. In our example we will only let users in the "admin" role have access to /secure (the SecurePages resource).

After the <web-resource-collection> we place an <auth-constraint> tag that tells the container "only the admin role has access to this area." For example,

<auth-constraint>
<description>only let the admin users login</description>
<role-name>admin</role-name>
</auth-constraint>

Step Three: Name all of the security roles in the web application

Later on in web.xml we define all of the security roles. Our example only has one role (admin), but if you imagine a real-world example where you have /managers and /peons, each with their own roles, then you would configure the "manager" and "peon" roles, but the <auth-constraint> for each resource will only list one role (e.g. under the <security-constraint> that has the pattern /managers/*, the <role-name> would be "manager").

Here is the simple <security-role> tag showing our only role (admin):

<security-role>
  <description>The Only Secure Role</description>
  <role-name>admin</role-name>
</security-role>

Step Four: Name all of the users/groups in the roles

So, we have listed all of our security roles, told the server that anyone in that one role is allowed access to a resource under /secure, but how do we set up the users that are in the given role? A "role" is just this abstract thing, but we need to tie it to the real security system. This is where we move away from the standards, and the particular server takes over.

If we are working with BEA WebLogic Server, we tie to the real users via the file WEB-INF\weblogic.xml. That file would have the following xml:

<weblogic-web-app>
  <security-role-assignment>
    <role-name>admin</role-name>
    <principal-name>system</principal-name>
  </security-role-assignment>
</weblogic-web-app>

We tie to the role name admin, and give the usernames, or groups that are part of that role. In this case, I have only granted access to /secure to the user "system."

To put it all together, so far we have set up the security roles for our Web application, named all of the users and groups that are part of that role, and set up a security condition: when a browser accesses /secure, only the users in the admin role will get through!

Authentication Options

Although we have defined the users that are allowed access to a resource, we need to tell the container how we want to authenticate the users. There are four authentication methods to choose from:

Authentication Method Description
BASIC

Use HTTP basic authentication. If we used this setting then the good ole pop up window will show trying to access /secure.

FORM

It is sometimes nice to be able to build your authentication into your Web pages. With FORM-based authentication we can do this! We will focus on this mechanism in the next section.

CLIENT-CERT

We can use client digital certificates to authenticate against.

DIGEST

Use HTTP digest authentication (advanced form of BASIC, but hasn't caught on to much).

This is a nice feature, being able to choose the authentication mechanism at deploy-time. Let's check out form based authentication, and walk through an example of setting it up.

FORM-based Authentication

  Related Reading:
Java Security, 2nd Edition

Java Security, 2nd Edition
By Scott Oaks
2nd Edition May 2001 (est.)
0-596-00157-6, Order Number: 1576
550 pages (est.), $39.95 (est.)

We will go through the simple steps required in setting up the standards-based FORM-based authentication.

  1. Configure the web.xml to use FORM-based authentication
  2. Build the login form

Step One: Configure the web.xml to use FORM-based authentication

Let's tell the container to use FORM-based authentication in our web.xml file.

<login-config>
  <auth-method>FORM</auth-method>
  <form-login-config>
    <form-login-page>/LoginForm.html</form-login-page>
    <form-error-page>/LoginError.html</form-error-page>
  </form-login-config>
</login-config>

First, we specify "FORM" as the auth-method (instead of BASIC, DIGEST, or CLIENT-CERT), and then we tell the system that the Web page LoginForm.html has the <FORM> which will authenticate a user. If we try to access a page under /secure we will first have to fill out the form in LoginForm.html and authenticate. If our authentication fails (we do not log in correctly as the system user), then we will be sent to LoginError.html.

Step Two: Build the login form

Now we build out login form. We have to follow a couple of conventions that are defined in the Servlet API specification:

So, our LoginForm.html will simply look like:

<form method="POST" action="j_security_check">

  Username: <input type="text"     name="j_username"><br />
  Password: <input type="password" name="j_password"><br />
  <br />

  <input type="submit" value="Login">
  <input type="reset"  value="Reset">

</form>

Let's say a browser tries to access something under /secure in our deployed Web application. The container will do the following:

  1. Save away the resource that the user was trying to access.
  2. Send back the LoginForm.html.
  3. When the user fills out the username and password and submits it back, the container tries to authenticate the user. If the auth fails the LoginError.html is sent back to the browser.
  4. If the authenticated user is part of the admin role (e.g. system user), the original resource will be sent back to the user, otherwise the LoginError.html will.

And that is it! Using FORM-based authentication is easy. You configure the web.xml to point to the correct login form and error page, and then make sure that the form follows the conventions of using j_security_check, j_username, and j_password.

Enforcing SSL

Lastly, we can declaratively control the level of security in the transport mechanism using the following tag in web.xml:

<user-data-constraint>
  <description>SSL not required</description>
  <transport-guarantee>NONE</transport-guarantee>
</user-data-constraint>

There are three possible values for the <transport-guarantee>:

Transport Description
NONE

No encryption is required (http is fine)

CONFIDENTIAL

The data must be encrypted, so that other parties can not observe the contents (e.g. enforce SSL)

INTEGRAL

The data must be transported so that the data cannot be changed in transit. Most servers use SSL for this value too, although in theory you could use some hashing algorithm, as encryption is not required

Conclusion

We have shown that you can configure many security options for your Web-based applications, adding support for a standard way to do FORM-based authentication that the Web container takes care of for you. Please download the sample Web application and test it out by trying to access /logintest/secure/ (assuming that you deploy the Web application as "logintest").

Dion Almaer is a Principal Technologist for The Middleware Company, and Chief Architect of TheServerSide.Com J2EE Community.


Return to ONJava.com.

Copyright © 2009 O'Reilly Media, Inc.