Web applications often require that certain parts of the system be secured. Some security requirements can be satisfied with standard security mechanisms, while others call for a customized approach. Sometimes, as a developer, you may need to use a combination of these two techniques. This article helps you examine the issues and techniques. It is excerpted from chapter 19 of the book The Complete Reference: Struts, written by James Holmes (McGraw-Hill/Osborne, 2004; ISBN: 0072231319 ).
FORM-based login is another variant of a container-managed login configuration. With FORM-based login, you supply a Web page (either a JSP or static HTML page) that contains the login form and a page to display if an error occurs. This provides a much more consistent look and feel for your application. The behavior of FORM-based login when a user is trying to access protected resources is similar to the behavior of BASIC login. To implement FORM-based login, you supply a Web page that has a form for login that must follow specific guidelines. The form must submit two parameters with the names j_usernameand j_password, holding the username and password respectively, to the j_security_checkURL. Optionally, you can also specify a Web page that will be displayed if a login error occurs. Here’s the login_form.htmlpage:
<html> <head> <title>ABC, Inc. Human Resources Portal</title> </head> <body> <font size="+1">ABC, Inc. Human Resources Portal Login</font><br> <hr width="100%" noshade="true"> <form action="j_security_check"> Username: <input type="text" name="j_username"/><br/> Password: <input type="password" name="j_password"/><br/> <input type="submit" value="Login"/> </form> </body> </html>
Next, change the login-configelement of web.xml to use FORM-based authentication:
Now, instead of displaying the standard dialog box, the browser displays the new page (albeit a little bland in this case). Once authenticated, the user is taken back to the index page, where the hidden link is now displayed.
A natural progression of these modifications is to place the login form on the main index page, thereby reducing an extra mouse click and page display. This approach is quite common in Web applications. Often, the main pages of applications have a login form on the welcome page. The main page provides lots of information to anyone. When you log in, however, the user experience becomes personalized for you. However, if you move the login form to the Mini HR index page, you will find that it will not work. When you submit your username and password, an error will occur. Tomcat generates the following error:
HTTP Status 400 – Invalid direct reference to form login page
Tomcat raises this error because the login page can only be managed by the container. Access by a user to a protected page is the only mechanism that should trigger display of the login page. In the container-managed authentication workflow, once a user is authenticated, the client is then redirected to the requested protected page. If the user browses directly to the login page, the protected resource to redirect to is undefined. In other words, if the user were to submit the form, the container would not know where to redirect the request.
There is no good work-around for this problem. This is one of the frustrations with FORM-based authentication and container-managed security—a simple change in requirements (e.g., put the login on the main page) causes you to rethink your security implementation. However, if you and your users can live with the constraints of container-managed security, it is a great way to provide robust security with minimal coding.
Container-Managed Secure Transport
The last container-managed security service to be discussed concerns transport-level security. This service operates by declaratively specifying whether pages should be accessed using HTTPS. This is specified using the user-data-constraint subelement of the security-constraintelement. Following is a sample from web.xml:
The key here is the transport-guaranteeelement. The values accepted are the following:
NONE No restrictions, normal HTTP
INTEGRAL Use HTTPS
CONFIDENTIAL Use HTTPS
It is important to note that the use of the user-data-constraint subelement does not require specification of an authentication constraint. This means that you can define Web resources that are secure but do not require authentication. This is useful, for example, when you are using application-managed authentication but still want to use a container-managed protocol. At one time, the servlet specification did not indicate how this constraint was to be handled. Some servers would not automatically redirect to HTTPS but instead would simply report an error and leave the user dumbfounded.
Tomcat 4 does redirect to HTTPS; however, it does not always redirect back to HTTP after leaving the constrained page. Also, the behavior seems to vary by browser. Fortunately, there is a more flexible solution for Struts applications, which is described in “Integrating Struts with SSL” later in this chapter. For the time being, you may want to experiment using Tomcat with HTTPS and setting the transport guarantee. Like other container-managed services, if you can get it to work for you without having to compromise your requirements, then it is worth pursuing.