Home Page Javascript Download Core Servlets & Java Server Java Cryptography Java in 60 Min A Day Javascript Tutorial About Us Contact Us
Site Search
Free Javascript Lessons
Newest Java Articles
Checkbox Changer
Check Entry
Check All
Block Key Press
Basic Validation
Auto Email Link
JavaScript Forms: Agree Before Entry
Auto Tab
JavaScript Calendars: Time Entered - Day Highlighted
JavaScript Calendars: Days Left
Related SE Keywords
Java virtual machine
Java Applet
Javascript Lesson
Javascript Tutorial
Java Programming
Java Games
Java Xml
Java String
Cryptography Extensions
Free Web Master Tools
 
JavascriptDownload.net > Free Javascript Lessons > Core Servlets & JavaServer Pages > 3- Declarative Security / Form-Based Authentication - Setting Up Usernames, Passwords, and Roles

Topics in This Chapter

  • Understanding the major aspects of Web application security

  • Authenticating users with HTML forms

  • Using BASIC HTTP authentication

  • Defining passwords in Tomcat

  • Designating protected resources with the security-constraint element

  • Using login-config to specify the authentication method

  • Mandating the use of SSL

  • Configuring Tomcat to use SSL

  • Talking to Web servers interactively

  • Creating your own Certificate Authority

  • Signing a server certificate

There are two major aspects to securing Web applications:

  1. Preventing unauthorized users from accessing sensitive data. This process involves access restriction (identifying which resources need protection and who should have access to them) and authentication (identifying users to determine if they are one of the authorized ones). Simple authentication involves the user entering a username and password in an HTML form or a dialog box; stronger authentication involves the use of X.509 certificates sent by the client to the server. The first aspect of Web security applies to virtually all secure applications. Even intranets at locations with physical access controls usually require some sort of user authentication.

  2. Preventing attackers from stealing network data while it is in transit. This process involves the use of Secure Sockets Layer (SSL) to encrypt the traffic between the browser and the server. This capability is generally reserved for particularly sensitive applications or for particularly sensitive pages within a larger application. After all, unless the attackers are on your local subnet, it is exceedingly difficult for them to gain access to your network traffic.

These two security aspects are mostly independent. The approaches to access restriction are the same regardless of whether or not you use SSL. With the exception of client certificates (which apply only to SSL), the approaches to authentication are also identical whether or not you use SSL.

Within the Web application framework, there are two general approaches to this type of security:

  1. Declarative security. With declarative security, the topic of this chapter, none of the individual servlets or JSP pages need any security-aware code. Instead, both of the major security aspects are handled by the server.

    To prevent unauthorized access, you use the Web application deployment descriptor (web.xml) to declare that certain URLs need protection, and which categories of users should have access to them. You also designate the authentication method that the server should use to identify users. At request time, the server automatically prompts users for usernames and passwords when they try to access restricted resources, automatically checks the results against a predefined set of usernames and passwords, and automatically keeps track of which users have previously been authenticated. This process is completely transparent to the servlets and JSP pages.

    To safeguard network data, you use the deployment descriptor to stipulate that certain URLs should only be accessible with SSL. If users try to use a regular HTTP connection to access one of these URLs, the server automatically redirects them to the HTTPS (SSL) equivalent.

  2. Programmatic security. With programmatic security, the topic of the next chapter, protected servlets and JSP pages at least partially manage their own security.

    To prevent unauthorized access, each servlet or JSP page must either authenticate the user or verify that the user has been authenticated previously.

    To safeguard network data, each servlet or JSP page has to check the network protocol used to access it. If users try to use a regular HTTP connection to access one of these URLs, the servlet or JSP page must manually redirect them to the HTTPS (SSL) equivalent.

3.1. Form-Based Authentication

The most common type of declarative security uses regular HTML forms. The developer uses the deployment descriptor to identify the protected resources and to designate a page that has a form to collect usernames and passwords. A user who attempts to access protected resources is redirected to the page containing the form. When the form is submitted, the server checks the username and password against a list of usernames, passwords, and roles (categories of users). If the login is successful and the user belongs to a role that is permitted access to the page, the user is sent to the page originally requested. If the login is unsuccessful, the user is sent to a designated error page. Behind the scenes, the system uses some variation of session tracking to remember which users have already been validated.

The whole process is automatic: redirection to the login page, checking of usernames and passwords, redirection back to the original resource, and tracking of already authenticated users are all performed by the container (server) in a manner that is completely transparent to the individual resources. However, there is one major caveat: The servlet specification explicitly says that form-based authentication is not guaranteed to work when the server is set to perform session tracking based on URL rewriting instead of cookies (the default session-tracking mechanism).

Core Warning

 

Depending on your server, form-based authentication might fail when you use URL rewriting as the basis of session tracking.


This type of access restriction and authentication is completely independent of the protection of the network traffic. You can stipulate that SSL be used for all, some, or none of your application, but doing so does not change the way you restrict access or authenticate users, nor does the use of SSL require your individual servlets or JSP pages to participate in the security process; redirection to the URL that uses SSL and encryption/decryption of the network traffic are all performed by the server in a manner that is transparent to the servlets and JSP pages.

Eight basic steps are required to set up your system to use this type of form-based security. We summarize the steps here, then give details on each step in the following subsections. All the steps except for the first are standardized and portable across all servers that support version 2.2 or later of the servlet API. Section 3.2 (Example: Form-Based Authentication) illustrates the concepts with a small application.

1.
Set up usernames, passwords, and roles. In this step, you designate a list of users and associate each with a password and one or more abstract roles (e.g., normal user or administrator). This is a completely server-specific process. In general, you'll have to read your server's documentation, but we summarize the process for Tomcat.

2.
Tell the server that you are using form-based authentication. Designate the locations of the login and login-failure page. This process uses the web.xml login-config element with an auth-method subelement of FORM and a form-login-config subelement that gives the locations of the two pages.

3.
Create a login page. This page must have a form with an ACTION of j_security_check, a METHOD of POST, a text field named j_username, and a password field named j_password.

4.
Create a page to report failed login attempts. This page can simply say something like "username and password not found" and perhaps give a link back to the login page.

5.
Specify which URLs should be password protected. For this step, you use the security-constraint element of web.xml. This element, in turn, uses web-resource-collection and auth-constraint subelements. The first of these (web-resource-collection) designates the URL patterns to which access should be restricted, and the second (auth-constraint) specifies the abstract roles that should have access to the resources at the given URLs.

6.
List all possible abstract roles (types of users) that will be grated access to any resource. Each abstract role is declared using the security-role element. The security-role element contains the required role-name element, which contains the name of the abstract role.

7.
Specify which URLs should be available only with SSL. If your server supports SSL, you can stipulate that certain resources are available only through encrypted HTTPS (SSL) connections. You use the user-data-constraint subelement of security-constraint for this purpose.

8.
Turn off the invoker servlet. Security settings are based on URLs, so you protect servlets by listing their URLs within the web-resource-collection element. The servlet URLs, in turn, are normally defined with the url-pattern element of servlet-mapping. However, many servers also have a default servlet URL of the form http://hostwebAppPrefix/servlet/ServletName. If you have this capability enabled, there are now two URLs that can invoke each servlet: the URL registered in servlet-mapping and the default (invoker servlet) URL. Remembering to protect both addresses is too hard. Instead, disable the invoker servlet, either globally for your server, or by mapping the /servlet/* pattern within your Web application.

Details follow.

Setting Up Usernames, Passwords, and Roles

When a user attempts to access a protected resource in an application that is using form-based authentication, the system automatically sends the user to an HTML form to ask for a username and password, verifies that the password matches the user, determines what abstract roles (regular user, administrator, executive, etc.) that user belongs to, and sees whether any of those roles has permission to access the resource. If so, the server redirects the user to the originally requested page. If not, the server redirects the user to an error page.

The good news regarding this process is that the server (container) does a lot of the work for you. The bad news is that the task of associating users with passwords and logical roles is server specific. So, although you would not have to change the web.xml file or any of the actual servlet and JSP code to move a secure Web application from system to system, you would still have to make custom changes on each system to set up the users and passwords.

In general, you will have to read your server's documentation to determine how to assign passwords and role membership to users. However, we summarize the process for Tomcat.

Setting Passwords with Tomcat

Tomcat permits advanced developers to configure custom username and password management schemes (e.g., accessing a database, looking in the UNIX /etc/passwd file, checking the Windows User Account settings, or making a Kerberos call). For details, see http://jakarta.apache.org/tomcat/tomcat-5.5-doc/realm-howto.html. However, this configuration is a lot of work, so Tomcat also provides a default mechanism for use in testing. With this mechanism, Tomcat stores usernames, passwords, and roles in tomcat_dir/conf/tomcat-users.xml. This file should contain an XML header followed by a tomcat-users element containing any number of role and user elements. Each role element should have a rolename attribute. Each user element should have three attributes: username, password (the plain text password), and roles (a comma-separated list of logical role names). Listing 3.1 presents a simple example that defines four users (valjean, bishop, javert, thenardier), each of whom belongs to two logical roles.

Note that the default Tomcat strategy of storing unencrypted passwords is a poor one for real deployed applications. First, an intruder who gains access to the server's file system can obtain all the passwords. Second, even system administrators who are authorized to access server resources should not be able to obtain users' passwords. In fact, because many users reuse passwords on multiple systems, passwords should never be stored in clear text. Instead, they should be encrypted with an algorithm that cannot easily be reversed. Then, when a user supplies a password, it is encrypted and the encrypted version is compared with the stored encrypted password. Nevertheless, the default Tomcat approach makes it easy to set up and test secure Web applications. Just keep in mind that for real applications you'll want to replace the simple file-based password scheme with something more robust (e.g., a database or a system call to Kerberos or the Windows User Account system).

Listing 3.1. tomcat_dir/conf/tomcat-users.xml (Sample)

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="lowStatus" />
  <role rolename="highStatus" />
  <role rolename="nobleSpirited" />
  <role rolename="meanSpirited" />

  <user username="valjean" password="forgiven"
        roles="lowStatus,nobleSpirited" />
  <user username="bishop" password="mercy"
        roles="lowStatus,nobleSpirited" />
  <user username="javert" password="strict"
        roles="highStatus,meanSpirited" />
  <user username="thenardier" password="grab"
        roles="lowStatus,meanSpirited" />
</tomcat-users>

Telling the Server You Are Using Form-Based Authentication; Designating Locations of Login and Login-Failure Pages

You use the login-config element in the deployment descriptor (web.xml) to control the authentication method. Recall from Chapter 1 (Using and Deploying Web Applications) that this file goes in the WEB-INF directory of your Web application. Although a few servers support nonstandard web.xml files (e.g., Tomcat has one in tomcat_dir/conf that provides defaults for multiple Web applications), those files are entirely server specific. We are addressing only the standard version that goes in the Web application's WEB-INF directory.

To use form-based authentication, supply a value of FORM for the auth-method subelement and use the form-login-config subelement to give the locations of the login (form-login-page) and login-failure (form-error-page) pages. In the next sections we explain exactly what these two files should contain. For now, however, note that nothing mandates that they use dynamic content. Thus, these pages can consist of either JSP or ordinary HTML.

For example, Listing 3.2 shows part of a web.xml file that stipulates that the container use form-based authentication. Unauthenticated users who attempt to access protected resources will be redirected to http://host/webAppPrefix/login.jsp. If they log in successfully, they will be returned to whatever resource they first attempted to access. If their login attempt fails, they will be redirected to http://host/webAppPrefix/login-error.html.

Listing 3.2. web.xml (Excerpt designating form-based authentication)

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation=
         "http://java.sun.com/xml/ns/j2ee
          http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">
  <security-constraint>...</security-constraint>
  <login-config>
    <auth-method>FORM</auth-method>
    <form-login-config>
      <form-login-page>/login.jsp</form-login-page>
      <form-error-page>/login-error.html</form-error-page>
    </form-login-config>
  </login-config>
</web-app>

Creating the Login Page

The login-config element tells the server to use form-based authentication and to redirect unauthenticated users to a designated page. Fine. But what should you put in that page? The answer is surprisingly simple: All the login page requires is a form with an ACTION of j_security_check, a text field named j_username, and a password field named j_password. And, because using GET defeats the whole point of password fields (protecting the password from prying eyes looking over the user's shoulder), all forms that have password fields should use a METHOD of POST. You never use GET with password fields because the password would show up in clear text in the browser's address bar. Note that j_security_check is a "magic" name; you don't preface it with a slash even if your login page is in a subdirectory of the main Web application directory. Listing 3.3 gives an example.

Listing 3.3. login.jsp

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD><TITLE>...</TITLE></HEAD>
<BODY>
...
<FORM ACTION="j_security_check" METHOD="POST">
<TABLE>
<TR><TD>User name: <INPUT TYPE="TEXT" NAME="j_username">
<TR><TD>Password: <INPUT TYPE="PASSWORD" NAME="j_password">
<TR><TH><INPUT TYPE="SUBMIT" VALUE="Log In">
</TABLE>
</FORM>
...
</BODY></HTML>

That was the page for logging in. What about a page for logging out? The session should time out eventually, but what if users want to log out immediately without closing the browser? The servlet specification mandates that invalidating the HttpSession should log users out and cause them to be reauthenticated the next time they try to access a protected resource. So, you could create a logout page by making a servlet or JSP page that looks up the session and calls invalidate on it. This is in contrast to BASIC authentication (see Section 3.3), where logging out is not supported without the user quitting and restarting the browser.

Restricting Direct Access to the Login Page

As we explained, when an unauthenticated user tries to access a protected resource, the server automatically redirects to the login page. Unfortunately, the servlet specification does not force compliant servers to use the "behind-the-scenes" redirecting (i.e., using the RequestDispatcher.forward method) to the JSP page specified in the form-login-page element. The servers are free to use the HttpServletResponse.sendRedirect method, and some modern servers do. The containers that use the sendRedirect method expose the full URL of the login page to the client. The unsuspecting user can later invoke this URL, attempting to either log in to the application for the first time (the user would not be authenticated yet), log in under a different username while already logged in, or by simply hitting the browser back button.

Neither does the servlet specification dictate what compliant servers should do if the user tries to access the login page directly, as in the outlined scenarios. Therefore, the outcome is highly server specific. The server might forward the user to a nonexisting page, resulting in an HTTP 404 error, or produce some other result not expected by the user. Obviously, neither of these outcomes is good.

We can partially avoid this unpredictable behavior by placing some logic into the login page (see Figure 3-1). The logic would need to protect two types of users from directly accessing the login page: an unauthenticated user (has not logged in yet) and an authenticated user (tries to access the login page having been logged in already).

Figure 3-1. When the client tries to access a protected resource, Weblogic 8.1 uses the response.sendRedirect method to send the client to the login page, exposing the login page's URL.


To protect a user who has already logged in, we would place the following code into our login.jsp.

<%
response.setHeader("Cache-Control",
                   "no-store, no-cache, must-revalidate");
response.setHeader("Pragma", "no-cache");
response.setDateHeader("Expires", -1);
// Check if user is already logged in
if (request.getRemoteUser() != null) {
  response.sendRedirect("logout-confirmation.jsp");
}
%>

The first line, which sets the HTTP version 1.1 response header Cache-Control to "no-store, no-cache, must-revalidate", ensures that the user will never see the browser-cached version of the login page. Similarly, to satisfy HTTP version 1.0, we also set the Pragma and Expires headers. The next few lines use the getRemoteUser method, which returns the username of the currently logged-in user. If the user is not logged in, it returns null. Thus, if getRemoteUser does, in fact, return a non-null value, we can be sure that this user has already been logged in and is invoking the login page directly. In this case, we simply redirect the user to some logout-confirmation.jsp, which gives the user the option to formally logout.

There isn't really a clean and easy way to protect the unauthenticated user from directly accessing the login page. One unclean way would be to blindly redirect every request for the login page to a protected resource (e.g., /protectedA.jsp), causing the server to trigger the authentication process, and "re-serving" the login page to the client as part of that process. This approach would solve the problem of an unauthenticated user directly invoking the login page. However, it would also introduce some side effects. What would happen if an unauthenticated user attempts to invoke another protected resource, /protectedB.jsp? The server would serve the login page, and if the login is successful, the user would be forwarded to /protectedA.jsp. However, the user asked to go to /protectedB.jsp! The logged in but frustrated user would now be forced to once again navigate through your Web site to get to /protectedB.jsp.

So, if your Web application is to be deployed on a server that uses sendRedirect to forward the user to the login page, you have to decide which side effect is more detrimental to your application and adjust accordingly.

More important, the problem with all the discussed approaches is that they are forcing you to write security-related code, which is antithetical to the declarative security model.

Creating the Page to Report Failed Login Attempts

The login page must contain a form with a special-purpose ACTION (j_security_check), a text field with a special name (j_username), and a password field with yet another reserved name (j_password). When the user attempts to access a protected resource, the server automatically presents the login page. The user fills out the login form and submits it. If the presented credentials (e.g., username and password) are those of a legal user but the user does not belong to the category of users able to access the requested resource, the server will reject the request with an HTTP error code 403 Forbidden. Remember that using the deployment descriptor, you can specify a custom page to be displayed when an HTTP error occurs. For details see Section 2.9 (Designating Pages to Handle Errors).

However, if the username and password are not those of a legal user, the server will automatically send the user to the login-failure page specified in the form-error-page element.

So, what is required to be in the login-failure page? Nothing! This page is arbitrary; it can contain a link to an unrestricted section of the Web application or a simple "login failed" message.

Specifying URLs That Should Be Password Protected

The login-config element tells the server which authentication method to use. Good, but how do you designate the specific URLs to which access should be restricted? Designating restricted URLs and describing the protection they should have is the purpose of the security-constraint element.

The security-constraint element contains four possible subelements: display-name (an optional element giving a name for IDEs to use), web-resource-collection (a required element that specifies the URLs that should be protected), auth-constraint (an optional element that designates the abstract roles that should have access to the URLs), and user-data-constraint (an optional element that specifies whether SSL is required). Note that multiple web-resource-collection entries are permitted within security-constraint.

For a quick example of the use of security-constraint, Listing 3.4 instructs the server to require passwords for all URLs of the form http://host/webAppPrefix/sensitive/blah. Users who supply passwords and belong to the administrator or executive logical roles should be granted access; all others should be denied access. The rest of this subsection provides details on the web-resource-collection, auth-constraint, and display-name elements. The role of user-dataconstraint is explained in a later subsection (Specifying URLs That Should Be Available Only with SSL).

Listing 3.4. web.xml (Excerpt specifying protected URLs)

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation=
         "http://java.sun.com/xml/ns/j2ee
          http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Sensitive</web-resource-name>
      <url-pattern>/sensitive/*</url-pattern>
    </web-resource-collection>
    <auth-constraint>
      <role-name>administrator</role-name>
      <role-name>executive</role-name>
    </auth-constraint>
  </security-constraint>
  <login-config>...</login-config>
</web-app>

web-resource-collection

This subelement of security-constraint identifies the resources that should be protected. Each security-constraint element must contain one or more web-resource-collection entries; all other securityconstraint subelements are optional. The web-resource-collection element consists of a web-resource-name element that gives an arbitrary identifying name, a url-pattern element that identifies the URLs that should be protected, an optional http-method element that designates the HTTP commands to which the protection applies (GET, POST, etc.; the default is all methods), and an optional description element providing documentation. For example, the following web-resource-collection entries (within a security-constraint element) specify that password protection should be applied to all documents in the proprietary directory (and subdirectories thereof) and to the delete-account.jsp page in the admin directory. Because security constraints apply to request the URL, not the physical directory, this security constraint would equally apply to any servlets mapped to URLs that contain the proprietary directory in them. For example, a servlet mapped with a pattern /proprietary/CompanySecretOfTheDayServlet would likewise be protected by the following security constraint:

<security-constraint>
  <web-resource-collection>
    <web-resource-name>Proprietary</web-resource-name>
    <url-pattern>/proprietary/*</url-pattern>
  </web-resource-collection>
  <web-resource-collection>
    <web-resource-name>Account Deletion</web-resource-name>
    <url-pattern>/admin/delete-account.jsp</url-pattern>
  </web-resource-collection>
  <!-- ... -->
</security-constraint>

When protecting form submissions, it's important that you protect the page that has the form as well as the servlet that the form submits to. A common mistake is to protect only the form and leave the servlet unprotected. This oversight lets the users bypass the form, either deliberately or accidentally (e.g., by following a bookmark), and access the servlet without being authenticated.

Core Warning

 

When protecting form submissions, make sure to protect the servlet that the form submits to in addition to the form page itself.


It is also important to note that the url-pattern applies only to clients that access the resources directly. In particular, it does not apply to pages that are accessed through the MVC architecture with a RequestDispatcher (see Chapter 15 of Volume 1) or by the similar means of jsp:forward or jsp:include (see Chapter 13 of Volume 1). This asymmetry is good if used properly. For example, with the MVC architecture a servlet looks up data, places it in beans, and forwards the request to a JSP page that extracts the data from the beans and displays it. You want to ensure that the JSP page is never accessed directly but instead is accessed only through the servlet that sets up the beans the page will use. The url-pattern and auth-constraint (see next subsection) elements can provide this guarantee by declaring that no user is permitted direct access to the JSP page. Note, however, that the simpler approach to this problem is to place the JSP pages inside the WEB-INF directory. This asymmetric behavior can catch developers off guard and allow them to accidentally provide unrestricted access to resources that should be protected.

Core Warning

 

These protections apply only to direct client access. The security model does not apply to pages accessed by means of a RequestDispatcher, jsp:forward, or jsp:include.


auth-constraint

Whereas the web-resource-collection element designates the URLs that should be protected, the auth-constraint element designates the users who should have access to these resources. It should contain one or more role-name elements identifying the class of users that have access and, optionally, a description element describing the role. For instance, the following part of the security-constraint element in web.xml states that only users who are designated as either Administrators or Big Kahunas (or both) should have access to the designated resource.

<security-constraint>
  <web-resource-collection>...</web-resource-collection>
  <auth-constraint>
    <role-name>administrator</role-name>
    <role-name>kahuna</role-name>
  </auth-constraint>
</security-constraint>

If you want all authenticated users to have access to a resource, use * as the role-name. To restrict anyone from accessing a group of resources, use an empty auth-constraint element (e.g., <auth-constraint/>). The empty auth-constraint element means that no roles have access. Although at first glance it appears pointless to deny access to all users, remember that these security restrictions apply only to direct client access. So, for example, suppose you had a JSP snippet that is intended to be inserted into another file with jsp:include (see Chapter 13 of Volume 1). Or, suppose you have a JSP page that is the forwarding destination of a servlet that is using a RequestDispatcher as part of the MVC architecture (see Chapter 15 of Volume 1). In both cases, users should be prohibited from directly accessing the JSP page. A security-constraint element with an empty auth-constraint element would enforce this restriction. However, as we mentioned, placing such resources inside the WEB-INF directory is the simpler solution.

display-name

This rarely used optional subelement of security-constraint gives a name to the security constraint entry. This name might be used by an IDE or other graphical tool.

Listing All Possible Abstract Roles

The servlet specification requires that all possible abstract roles are listed within the web.xml file. This means that any role used within any of the security-constraint elements must be separately declared. You declare the abstract roles using one or more security-role elements. Each security-role element contains an optional description element and a required role-name element. For example, suppose you had one security-constraint element with auth-constraint entries for teacher and student, another security-constraint element with auth-constraint entries for teacher and principal, and a third security-constraint element with auth-constraint entries for principal, administrator, and dean. You would then use security-role elements to list the unique names as follows:

<security-role>
  <role-name>teacher</role-name>
</security-role>
<security-role>
  <role-name>student</role-name>
</security-role>
<security-role>
  <role-name>principal</role-name>
</security-role>
<security-role>
  <role-name>administrator</role-name>
</security-role>
<security-role>
  <role-name>dean</role-name>
</security-role>

Specifying URLs That Should Be Available Only with SSL

Suppose your servlet or JSP page collects credit card numbers. User authentication keeps out unauthorized users but does nothing to protect the network traffic. So, for instance, an attacker who runs a packet sniffer on the end user's LAN could see that user's credit card number. This scenario is exactly what SSL protects against—it encrypts the traffic between the browser and the server.

Use of SSL does not change the basic way that form-based authentication works. Regardless of whether you are using SSL, you use the login-config element to indicate that you are using form-based authentication and to identify the login and login-failure pages. With or without SSL, you designate the protected resources with the url-pattern subelement of web-resource-collection. None of your servlets or JSP pages need to be modified or moved to different locations when you enable or disable SSL. That's the beauty of declarative security.

The user-data-constraint subelement of security-constraint can mandate that certain resources be accessed only with SSL. So, for example, attempts to access https://host/webAppPrefix/specialURL are handled normally, whereas attempts to access http://host/webAppPrefix/specialURL are redirected to the https URL. This behavior does not mean that you cannot supply an explicit https URL for a hypertext link or the ACTION of a form; it just means that you aren't required to. You can stick with the simpler and more easily maintained relative URLs and still be assured that certain URLs will only be accessed with SSL.

The user-data-constraint element, if used, must contain a transportguarantee subelement (with legal values NONE, INTEGRAL, or CONFIDENTIAL) and can optionally contain a description element. A value of NONE for transport-guarantee puts no restrictions on the communication protocol used. Because NONE is the default, there is little point in using user-data-constraint or transport-guarantee if you specify NONE. A value of INTEGRAL means that the communication must be of a variety that prevents data from being changed in transit without detection. A value of CONFIDENTIAL means that the data must be transmitted in a way that prevents anyone who intercepts it from reading it. Although in principle (and perhaps in future HTTP versions) there may be a distinction between INTEGRAL and CONFIDENTIAL, in current practice they both simply mandate the use of SSL.

For example, the following instructs the server to permit only https connections to the associated resource:

<security-constraint>
  <!-- ... -->
  <user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
  </user-data-constraint>
</security-constraint>

In addition to simply requiring SSL, the servlet API provides a way to stipulate that users must authenticate themselves with client certificates. You supply a value of CLIENT-CERT for the auth-method subelement of login-config (discussed earlier in this section). However, only servers that have full J2EE support are required to support this capability.

Now, although the method of prohibiting non-SSL access is standardized, servers that are compliant with the servlet 2.4 and JSP 2.0 specifications are not required to support SSL. So, Web applications that use a transport-guarantee of CONFIDENTIAL (or, equivalently, INTEGRAL) are not necessarily portable. For example, JRun and ServletExec are usually used as plug-ins in Web servers like Apache or Internet Information Server (IIS). In this scenario, the network traffic between the client and the Web server is encrypted with SSL, but the local traffic from the Web server to the servlet/JSP container is not encrypted. Consequently, a CONFIDENTIAL transport-guarantee will fail. Tomcat, however, can be set up to use SSL directly. Details on this process are given in Section 3.5 (Configuring Tomcat to Use SSL). Some server plug-ins maintain SSL even on the local connection between the main Web server and the servlet/JSP engine; for example, the BEA WebLogic plug-in for IIS, Apache, and Netscape Enterprise Server does so. Furthermore, integrated application servers like the standalone version of WebLogic have no "separate" servlet and JSP engine, so SSL works exactly as described here. Nevertheless, it is important to realize that these features, although useful, are not mandated by the servlet and JSP specifications.

Core Warning

 

Web applications that rely on SSL are not necessarily portable.


Turning Off the Invoker Servlet

When you restrict access to certain resources, you do so by specifying the URL patterns to which the restrictions apply. This pattern, in turn, matches a pattern that you set with the servlet-mapping web.xml element. See Section 2.4 (Assigning Names and Custom URLs). However, most servers use an "invoker servlet" that provides a default URL for servlets: http://host/webAppPrefix/servlet/ServletName. You need to make sure that users don't access protected servlets with this URL, thus bypassing the access restrictions that were set by the url-pattern subelement of web-resource-collection.

For example, suppose that you use security-constraint, web-resource-collection, and url-pattern to say that the URL /admin/DeclareChapter3 should be protected. You also use the auth-constraint and role-name elements to say that only users in the director role can access this URL. Next, you use the servlet and servlet-mapping elements to say that the servlet BankruptcyServlet.class in the disaster package should correspond to /admin/DeclareChapter3. Now, the security restrictions are in force when clients use the URL http://host/webAppPrefix/admin/DeclareChapter3. No restrictions apply to http://host/webAppPrefix/servlet/disaster.BankruptcyServlet. Oops.

Section 2.5 (Disabling the Invoker Servlet) discusses server-specific approaches to turning off the invoker. The most portable approach, however, is to simply remap the /servlet/* pattern in your Web application so that all requests that include the pattern are sent to the same servlet. To remap the pattern, you first create a simple servlet that prints an error message or redirects users to the top-level page. Then, you use the servlet and servlet-mapping elements (Section 2.4) to send requests that include the /servlet/* pattern to that servlet. Listing 3.5 gives a brief example.

Listing 3.5. web.xml (Excerpt redirecting requests from default servlet URLs to an error-message servlet)

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation=
         "http://java.sun.com/xml/ns/j2ee
          http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
         version="2.4">
  <servlet>
    <servlet-name>NoInvoker</servlet-name>
    <servlet-class>coreservlets.NoInvokerServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>NoInvoker</servlet-name>
    <url-pattern>/servlet/*</url-pattern>
  </servlet-mapping>
</web-app>

 
Add Comment
 
homepage   |  about us  |  contact us
Powered By teknonova.com