The Java EE 6 Tutorial, Volume I

Chapter 25 Getting Started Securing Web Applications

A web application is an application that is accessed using a web browser over a network such as the Internet or a company's intranet. As discussed in Chapter 24, Getting Started Securing Enterprise Applications, the JavaTM EE platform uses a distributed multi-tiered application model. As discussed in Distributed Multitiered Applications, web applications run in the web-tier.

Web applications contain resources that can be accessed by many users. These resources often traverse unprotected, open networks, such as the Internet. In such an environment, a substantial number of web applications will require some type of security. The ways to implement security for Java EE web applications are discussed in a general way in Securing Containers. This chapter provides more detail and a few examples that explore these security services as they relate to web components.

Both types of web applications can be secured using the same security model:

Securing applications and their clients in the business tier and the EIS tier is discussed in Chapter 24, Getting Started Securing Enterprise Applications.

The following topics are included in this chapter:

Overview of Web Application Security

In the Java EE platform, web components provide the dynamic extension capabilities for a web server. Web components are either Java servlets, JSF pages, or web service endpoints. The interaction between a web client and a web application is illustrated in Figure 25–1.

Figure 25–1 Java Web Application Request Handling

Diagram of steps in web application request handling,
showing web client, HttpServlet request, web and JavaBeans components, and
HttpServlet response

Web components are supported by the services of a runtime platform called a web container. A web container provides services such as request dispatching, security, concurrency, and life-cycle management. Certain aspects of web application security can be configured when the application is installed, or deployed, to the web container. Annotations and/or deployment descriptors are used to relay information to the deployer about security and other aspects of the application. Specifying this information in annotations or in the deployment descriptor helps the deployer set up the appropriate security policy for the web application. Any values explicitly specified in the deployment descriptor override any values specified in annotations.

Security for Java EE web applications can be implemented in the following ways:

Some of the material in this chapter builds on material presented earlier in this tutorial. In particular, this chapter assumes that you are familiar with the information in the following chapters:

Using Deployment Descriptors to Secure Web Applications

Web applications are created by application developers who give, sell, or otherwise transfer the application to an application deployer for installation into a runtime environment. Application developers communicate how the security is to be set up for the deployed application by the use of the deployment descriptor mechanism or by the use of annotations. When this information is passed on to the deployer, the deployer uses this information to define method permissions for security roles, set up user authentication, and set up the appropriate transport mechanism. If you don’t define security requirements, the deployer will have to determine the security requirements independently.

Many elements necessary for security in a web application cannot, as yet, be specified as annotations for all types of web applications. Therefore, in this volume of the tutorial, we describe how to secure web applications using deployment descriptors only. For information on using annotations to secure web applications, refer to the following sources:

Introduction to Web Application Deployment Descriptors

The web application deployment descriptor file does pretty much what it's name says it does: it describes how the web application should be deployed. The web application deployment descriptor describes a lot more about a web application than just its security information, but this chapter only discusses the elements of the application deployment descriptor that relate to security.

For web applications written using the Java programming language, the web application deployment descriptor is written using the EXtensible Markup Language (XML) syntax. The web application deployment descriptor is named web.xml, and, when included with a web application, it must reside in a WEB-INF subdirectory at the web application root. The contents of this file direct a deployment tool to deploy a module or application with the specified security settings, and describes other specific configuration requirements and/or container options.

The following XML code is an example of the elements in a deployment descriptor that apply specifically to declaring security for web applications or for resources within web applications. This example comes from An Example of Security, from the Java Servlet Specification, Version 3.0.

<?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_5.xsd"
		version=?2.5?>

		<display-name>A Secure Application</display-name>
		<servlet>
			<servlet-name>catalog</servlet-name>
			<servlet-class>com.mycorp.CatalogServlet</servlet-class>
			<init-param>
				<param-name>catalog</param-name>
				<param-value>Spring</param-value>
			</init-param>

			<!-- Defining Security Roles -->

			<security-role-ref>
				<role-name>MGR</role-name>
				<!-- role name used in code -->
				<role-link>manager</role-link>
			</security-role-ref>
		</servlet>
		<security-role>
			<role-name>manager</role-name>
		</security-role>
		<servlet-mapping>
			<servlet-name>catalog</servlet-name>
			<url-pattern>/catalog/*</url-pattern>
		</servlet-mapping>

		<!-- Defining A Security Constraint -->

		<security-constraint>
			<!-- Specifying the Resources to be Protected -->

			<web-resource-collection>
				<web-resource-name>SalesInfo</web-resource-name>
				<url-pattern>/salesinfo/*</url-pattern>
				<http-method>GET</http-method>
				<http-method>POST</http-method>
			</web-resource-collection>
			<!-- Specifying which Users Can Access Protected Resources -->

			<auth-constraint>
				<role-name>manager</role-name>
			</auth-constraint>
			<!-- Specifying Secure Transport using SSL  -->

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

		<!-- Specifying an Authentication Method -->
		<login-config>
			<auth-method>BASIC</auth-method>
			<realm-name>file</realm-name>
		</login-config>
</web-app>

Even if you are simply using the deployment descriptor to specify security, there are some structural elements that must be included in this file in order for it to work properly. For example, the <security-constraint> element is a sub-element of the <web-app> element, so the <web-app> element must always be included, and it must indicate the version of the web application schema (2.4 or 2.5) it is using. The elements that are specified within the deployment descriptor must comply with the rules for processing that version of the deployment descriptor. Version 3.0 of the Java Servlet Specification, which can be downloaded at http://jcp.org/en/jsr/detail?id=315, contains more information regarding the structure of deployment descriptors.

XML files are hierarchical. The elements must be specified in a particular order within the deployment descriptor, between elements that are its parent. To visually see an example of how the deployment descriptor elements are nested within their parent elements, refer to the elements within the <security-constraint> element above, which is itself nested within <web-app> elements. For this example, the lines have been indented to emphasize the nesting aspect of the file, but the file itself ignores the formatting and relies only on the elements and their content for its processing. Information about the application is specified as a value between the opening (<element-name>) and closing (</element-name>) elements. For example, between the opening <transport-guarantee> element and the closing </transport-guarantee> element, there is the value CONFIDENTIAL, which describes which type of transport guarantee should be used for this application.

The following sections describe each of the security elements of a deployment descriptor in more detail, listing all of the options available for each element:

Some of the elements of web application security must be addressed in server configuration files rather than in the deployment descriptor or annotations for the web application. Configuring security on the Enterprise Server is discussed in the following sections and books:

Specifying Security Constraints

A security constraint is used to define the access privileges to a collection of resources using their URL mapping. The following elements can be part of a security constraint:

Specifying a Web Resource Collection

A web resource collection consists of the following sub-elements:

Specifying an Authorization Constraint

An authorization constraint (auth-constraint) contains the role-name element. You can use as many role-name elements as needed here.

An authorization constraint establishes a requirement for authentication and names the roles authorized to access the URL patterns and HTTP methods declared by this security constraint. If there is no authorization constraint, the container must accept the request without requiring user authentication. If there is an authorization constraint, but no roles are specified within it, the container will not allow access to constrained requests under any circumstances. The role name(s) specified here must either correspond to the role name of one of the <security-role> elements defined for this web application, or be the specially reserved role name *, which is a compact syntax for indicating all roles in the web application. Role names are case sensitive. The roles defined for the application must be mapped to users and groups defined on the server. For more information about security roles, read Working with Security Roles.

Specifying a Secure Connection

A user data constraint (<TutorialUser-data-constraint> in the deployment descriptor) contains the <transport-guarantee> element. A user data constraint can be used to require that a protected transport layer connection such as HTTPS (HTTP over SSL) be used for all constrained URL patterns and HTTP methods specified in the security constraint. The choices for transport guarantee include CONFIDENTIAL, INTEGRAL, or NONE. If you specify CONFIDENTIAL or INTEGRAL as a security constraint, it generally means that the use of SSL is required, and that type of security constraint applies to all requests that match the URL patterns in the web resource collection and not just to the login dialog box.

The strength of the required protection is defined by the value of the transport guarantee. Specify CONFIDENTIAL when the application requires that data be transmitted so as to prevent other entities from observing the contents of the transmission. Specify INTEGRAL when the application requires that the data be sent between client and server in such a way that it cannot be changed in transit. Specify NONE to indicate that the container must accept the constrained requests on any connection, including an unprotected one.

The user data constraint is handy to use in conjunction with basic and form-based user authentication. When the login authentication method is set to BASIC or FORM, passwords are not protected, meaning that passwords sent between a client and a server on an unprotected session can be viewed and intercepted by third parties. Using a user data constraint with the user authentication mechanism can alleviate this concern. Configuring a user authentication mechanism is described in Specifying an Authentication Mechanism.

To guarantee that data is transported over a secure connection, ensure that SSL support is configured for your server. If your server is the Sun Java System Enterprise Server, SSL support is already configured. If you are using another server, consult the documentation for that server for information on setting up SSL support. More information on configuring SSL support on the Enterprise Server can be found in Establishing a Secure Connection Using SSL and in the Sun GlassFish Enterprise Server v3 Administration Guide.


Note –

Good Security Practice: If you are using sessions, after you switch to SSL you should never accept any further requests for that session that are non-SSL. For example, a shopping site might not use SSL until the checkout page, and then it might switch to using SSL to accept your card number. After switching to SSL, you should stop listening to non-SSL requests for this session. The reason for this practice is that the session ID itself was not encrypted on the earlier communications. This is not so bad when you’re only doing your shopping, but after the credit card information is stored in the session, you don’t want a bad guy trying to fake the purchase transaction against your credit card. This practice could be easily implemented using a filter.


Specifying Separate Security Constraints for Different Resources

You can create a separate security constraint for different resources within your application. For example, you could allow users with the role of PARTNER access to the GET and POST methods of all resources with the URL pattern /acme/wholesale/*, and allow users with the role of CLIENT access to theGET and POST methods of all resources with the URL pattern /acme/retail/*. An example of a deployment descriptor that would demonstrate this functionality is the following:

<!-- SECURITY CONSTRAINT #1 -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>wholesale</web-resource-name>
        <url-pattern>/acme/wholesale/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>PARTNER</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

<!-- SECURITY CONSTRAINT #2 -->
<security-constraint>
    <web-resource-collection>
        <web-resource-name>retail</web-resource-name>
        <url-pattern>/acme/retail/*</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>CLIENT</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

When the same url-pattern and http-method occur in multiple security constraints, the constraints on the pattern and method are defined by combining the individual constraints, which could result in unintentional denial of access. The Java Servlet 3.0 Specification (downloadable from http://jcp.org/en/jsr/detail?id=315) gives more detail and an example that illustrates the combination of constraints and how the declarations will be interpreted.

Specifying an Authentication Mechanism

The login configuration element is separate from the security-constraint element, as there can be multiple security constraints applying to multiple resources, but the same authentication method will apply to all constrained resources in an application. The login-config element is used to specify the user authentication method to be used for access to web content, the realm in which the user will be authenticated (in the case of basic authentication), and, in the case of form-based login, additional attributes. When specified, the user must be authenticated before access to any resource that is constrained by a security constraint will be granted.

The sub-element auth-method configures the authentication mechanism for the web application. The element content must be either NONE, BASIC, DIGEST, FORM, or CLIENT-CERT. The realm-name element indicates the realm name to use when the basic authentication scheme is chosen for the web application. The form-login-config element specifies the login and error pages that should be used when FORM based login is specified.


Note –

Another way to specify form-based authentication is to use the authenticate, login, and logout methods of HttpServletRequest, as discussed in Authenticating Users Programmatically.


When you try to access a web resource that is constrained by a security-constraint element, the web container activates the authentication mechanism that has been configured for that resource. The authentication mechanism you choose specifies how the user is prompted to login. If the <login-config> element is present, and the <auth-method> element contains a value other than NONE, the user must be authenticated before it can access any resource that is constrained by the use of a security-constraint element in the same deployment descriptor (read Specifying Security Constraints for more information on security constraints). If you do not specify an authentication mechanism, authentication of the user is not required.

Before you can authenticate a user, you must have a database of user names, passwords, and roles configured on your web or application server. For information on setting up the user database, refer to Managing Users and Groups on the Enterprise Server in this tutorial or the Sun GlassFish Enterprise Server v3 Administration Guide.

The choices for authentication mechanisms are discussed further in the following sections:

HTTP Basic Authentication

Specifying HTTP Basic Authentication requires that the server request a user name and password from the web client and verify that the user name and password are valid by comparing them against a database of authorized users in the specified or default realm.

    When basic authentication is declared, the following actions occur:

  1. A client requests access to a protected resource.

  2. The web server returns a dialog box that requests the user name and password.

  3. The client submits the user name and password to the server.

  4. The server authenticates the user in the specified realm and, if successful, returns the requested resource.

Figure 25–2 shows what happens when you specify HTTP basic authentication.

Figure 25–2 HTTP Basic Authentication

Diagram of four steps in HTTP basic authentication between
client and server

The following example shows how to specify basic authentication in your deployment descriptor:

<login-config>
		<auth-method>BASIC</auth-method>
		<realm-name>file</realm-name>
</login-config>

HTTP basic authentication is not a secure authentication mechanism. Basic authentication sends user names and passwords over the Internet as text that is Base64 encoded, and the target server is not authenticated. This form of authentication can expose user names and passwords. If someone can intercept the transmission, the user name and password information can easily be decoded. However, when a secure transport mechanism, such as SSL, or security at the network level, such as the IPSEC protocol or VPN strategies, is used in conjunction with basic authentication, some of these concerns can be alleviated. To specify a secure transport mechanism, use the elements described in Specifying a Secure Connection.

Example: Basic Authentication with JAX-WS is an example application that uses HTTP basic authentication in a JAX-WS service.

Form-Based Authentication

    Form-based authentication allows the developer to control the look and feel of the login authentication screens by customizing the login screen and error pages that an HTTP browser presents to the end user. When form-based authentication is declared, the following actions occur:

  1. A client requests access to a protected resource.

  2. If the client is unauthenticated, the server redirects the client to a login page.

  3. The client submits the login form to the server.

  4. The server attempts to authenticate the user.

    1. If authentication succeeds, the authenticated user’s principal is checked to ensure it is in a role that is authorized to access the resource. If the user is authorized, the server redirects the client to the resource using the stored URL path.

    2. If authentication fails, the client is forwarded or redirected to an error page.

Figure 25–3 shows what happens when you specify form-based authentication.

Figure 25–3 Form-Based Authentication

Diagram of four steps in form-based authentication between
client and server

The following example shows how to declare form-based authentication in your deployment descriptor:

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>file</realm-name>
    <form-login-config>
        <form-login-page>/logon.jsp</form-login-page>
        <form-error-page>/logonError.jsp</form-error-page>
    </form-login-config>
</login-config>

The login and error page locations are specified relative to the location of the deployment descriptor. Examples of login and error pages are shown in Creating the Login Form and the Error Page.

Form-based authentication is not particularly secure. In form-based authentication, the content of the user dialog box is sent as plain text, and the target server is not authenticated. This form of authentication can expose your user names and passwords unless all connections are over SSL. If someone can intercept the transmission, the user name and password information can easily be decoded. However, when a secure transport mechanism, such as SSL, or security at the network level, such as the IPSEC protocol or VPN strategies, is used in conjunction with form-based authentication, some of these concerns can be alleviated. To add a protected transport in your application, use the elements described in Specifying a Secure Connection.

The section Example: Form-Based Authentication with a Servlet is an example application that uses form-based authentication.

Using Login Forms

When creating a form-based login, be sure to maintain sessions using cookies or SSL session information.

As shown in Form-Based Authentication, for authentication to proceed appropriately, the action of the login form must always be j_security_check. This restriction is made so that the login form will work no matter which resource it is for, and to avoid requiring the server to specify the action field of the outbound form. The following code snippet shows how the form should be coded into the HTML page:

<form method="POST" action="j_security_check">
<input type="text" name="j_username">
<input type="password" name="j_password">
</form>

HTTPS Client Authentication

HTTPS Client Authentication requires the client to possess a Public Key Certificate (PKC). If you specify client authentication, the web server will authenticate the client using the client’s public key certificate.

HTTPS Client Authentication is a more secure method of authentication than either basic or form-based authentication. It uses HTTP over SSL (HTTPS), in which the server authenticates the client using the client’s Public Key Certificate (PKC). Secure Sockets Layer (SSL) technology provides data encryption, server authentication, message integrity, and optional client authentication for a TCP/IP connection. You can think of a public key certificate as the digital equivalent of a passport. It is issued by a trusted organization, which is called a certificate authority (CA), and provides identification for the bearer.

Before using HTTP Client Authentication, you must make sure that the following actions have been completed:

The following example shows how to declare HTTPS client authentication in your deployment descriptor:

<login-config>
    <auth-method>CLIENT-CERT</auth-method>
</login-config>

An example demonstrating HTTPS client authentication may be available in Part VII, Security, in The Java EE 6 Tutorial, Volume II.

Mutual Authentication

With mutual authentication, the server and the client authenticate one another. There are two types of mutual authentication:

    When using certificate-based mutual authentication, the following actions occur:

  1. A client requests access to a protected resource.

  2. The web server presents its certificate to the client.

  3. The client verifies the server’s certificate.

  4. If successful, the client sends its certificate to the server.

  5. The server verifies the client’s credentials.

  6. If successful, the server grants access to the protected resource requested by the client.

Figure 25–4 shows what occurs during certificate-based mutual authentication.

Figure 25–4 Certificate-Based Mutual Authentication

Diagram of six steps in mutual authentication with certificates

    In user name- and password-based mutual authentication, the following actions occur:

  1. A client requests access to a protected resource.

  2. The web server presents its certificate to the client.

  3. The client verifies the server’s certificate.

  4. If successful, the client sends its user name and password to the server, which verifies the client’s credentials.

  5. If the verification is successful, the server grants access to the protected resource requested by the client.

Figure 25–5 shows what occurs during user name- and password-based mutual authentication.

Figure 25–5 User Name- and Password-Based Mutual Authentication

Diagram of five steps in mutual authentication with user
name and password

Digest Authentication

Like HTTP Basic Authentication, HTTP Digest Authentication authenticates a user based on a username and a password. However, unlike HTTP Basic Authentication, HTTP Digest Authentication does not send user passwords over the network. In HTTP Digest authentication, the client sends a one-way cryptographic hash of the password (and additional data). Although passwords are not sent on the wire, HTTP Digest authentication requires that clear text password equivalents be available to the authenticating container so that it can validate received authenticators by calculating the expected digest.

The following example shows how to declare HTTP Digest authentication in your deployment descriptor:

<login-config>
    <auth-method>DIGEST</auth-method>
</login-config>

Working with Security Roles

In an application, a role is an abstract name for a group of users. A role can be compared to a key that can open a lock. Many people might have a copy of the key. The lock doesn’t care who you are, only that you have the right key.

For example, in a corporation, you might have the roles Director, Manager, HR, and Employee. When an application developer is creating an internal payroll website, the developer would use the same set of data for all of its corporate users, but would allow different access to the data depending on the role the user is in. For example, a person in the role of HR would have permission to create new Employees, and to modify the payroll information for Employees. The Employee would be able to view their own payroll information, but would not be able to change some of the data, such as their pay rate, but could change some other data, such as their address or dependent information. The users' assigned role determines what permissions that user is granted for access to a particular set of resources in an application.

The following elements in a deployment descriptor use security roles in some capacity:

Reviewing Security Concepts

If you read Working with Realms, Users, Groups, and Roles, you will remember the following information:

Declaring Security Roles

You can declare security role names used in web applications using the security-role element of the deployment descriptor. Use this element to list all of the security roles that you have referenced in your application, and also in conjunction with the security-role-ref element (see Declaring and Linking Role References.)

The following snippet of a deployment descriptor is taken from the simple sample application. This snippet declares the roles that will be used in the application using the security-role element, and specifies which of these roles is authorized to access protected resources using the auth-constraint element.

<security-constraint>
    <web-resource-collection>
        <web-resource-name>Protected Area</web-resource-name>
        <url-pattern>/jsp/security/protected/*</url-pattern>
        <http-method>PUT</http-method>
        <http-method>DELETE</http-method>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>manager</role-name>
    </auth-constraint>
</security-constraint>

 <!-- Security roles used by this web application -->
<security-role>
    <role-name>manager</role-name>
</security-role>
<security-role>
    <role-name>employee</role-name>
</security-role>

In this example, the security-role element lists all of the security roles used in the application: manager and employee. This enables the deployer to map all of the roles defined in the application to users and groups defined on the Enterprise Server.

The auth-constraint element specifies the role, manager, that can access the HTTP methods PUT, DELETE, GET, POST located in the directory specified by the url-pattern element (/jsp/security/protected/*).

Mapping Security Roles to Enterprise Server Groups

To map security roles defined in applications to Enterprise Server principals and groups, use the security-role-mapping element in the runtime deployment descriptor (DD). The runtime deployment descriptor is different from the application deployment descriptor file. The runtime deployment descriptor is an XML file that contains information such as the context root of the web application and the mapping of the portable names of an application’s resources to the Enterprise Server resources. The Enterprise Server web application runtime DD is located in the /WEB-INF/ directory along with the web application deployment descriptor. Runtime deployment descriptors are named sun-web.xml, sun-application.xml, or sun-ejb-jar.xml.

The following example demonstrates how to do this mapping in the sun-web.xml file, which is the file used for web applications:

<sun-web-app>

      <security-role-mapping>
        <role-name>CEO</role-name>
        <principal-name>Schwartz</principal-name>
    </security-role-mapping>

    <security-role-mapping>
        <role-name>Admin</role-name>
        <group-name>director</group-name>
    </security-role-mapping>

    ...

</sun-web-app>

A role can be mapped to specific principals, specific groups, or both. The principal or group names must be valid principals or groups in the current default realm, or in the realm specified in the login-config element. In this example, the role of CEO that is used in the application is mapped to a principal named Schwartz that exists on the application server. Mapping a role to a specific principal is useful when the person occupying that role may change. For this application, you would only need to modify the runtime deployment descriptor and not search and replace throughout the application for references to this principal.

Also in this example, the role of Admin is mapped to a group of users who are assigned the group name of director. This is useful because the group of people authorized to access director-level administrative data only has to be maintained on the Enterprise Server. The application developer does not need to know who these people are, just define the group of people who will be given access to the information.

The role-name must match the role-name in the security-role element of the corresponding application deployment descriptor (web.xml, ejb-jar.xml) or the role name defined in an @DeclareRoles annotation.

Sometimes the role names used in the application are the same as the group names defined on the Enterprise Server. Under these circumstances, you can use the Admin Console to define a default principal-to-role-mapping that applies to the entire Enterprise Server instance. From the Admin Console, select Configuration, then Security, then check the Enable box beside Default Principal to Role Mapping. For more information, read the Sun GlassFish Enterprise Server v3 Administration Guide.

Using Programmatic Security with Web Applications

Programmatic security is used by security-aware applications when declarative security alone is not sufficient to express the security model of the application. The following topics are discussed in this section:

Authenticating Users Programmatically

Servlet 3.0 specifies the following methods of the HttpServletRequest interface that enable you to authenticate users for a web application programmatically:

The following example code shows how to use the login and logout methods:

package test;

import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigDecimal;
import javax.ejb.EJB;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name="TutorialServlet", urlPatterns={"/TutorialServlet"})
public class TutorialServlet extends HttpServlet {
    @EJB
    private ConverterBean converterBean;

    /**
     * Processes requests for both HTTP <code>GET</code> 
		* and <code>POST</code> methods.
     * @param request servlet request
     * @param response servlet response
     * @throws ServletException if a servlet-specific error occurs
     * @throws IOException if an I/O error occurs
     */
    protected void processRequest(HttpServletRequest request, 
			HttpServletResponse response)
    throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {

            out.println("<html>");
            out.println("<head>");
            out.println("<title>Servlet TutorialServlet</title>");
            out.println("</head>");
            out.println("<body>");
            request.login("TutorialUser", "TutorialUser");
            BigDecimal result = converterBean.dollarToYen(new BigDecimal("1.0"));
            out.println("<h1>Servlet TutorialServlet result of dollarToYen= " + result + "</h1>");
            out.println("</body>");
            out.println("</html>");
        } catch (Exception e) {
            throw new ServletException(e);
        } finally {
            request.logout();
            out.close();
        }
    }
}

This code sample shows how to use the authenticate method:

package com.sam.test;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;

public class TestServlet extends HttpServlet {

    protected void processRequest(HttpServletRequest request, 
			HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            request.authenticate(response);
            out.println("Authenticate Successful");

        } finally {
            out.close();
        }
    } 

Checking Caller Identity Programmatically

In general, security management should be enforced by the container in a manner that is transparent to the web component. The security API described in this section should be used only in the less frequent situations in which the web component methods need to access the security context information.

Servlet 3.0 specifies the following methods of the HttpServletRequest interface that enable you to verify a caller's identity programmatically, and to use that information to grant or deny access to data:

Your application can make business logic decisions based on the information obtained using these APIs.

Example Code for Programmatic Security

The following code demonstrates the use of programmatic security for the purposes of programmatic login.

package enterprise.programmatic_login;

import java.io.*;
import java.net.*;

import javax.annotation.security.DeclareRoles;
import javax.servlet.*;
import javax.servlet.http.*;

@DeclareRoles("javaee6user")
public class LoginServlet extends HttpServlet {

    /** 
     * Processes requests for both HTTP GET and POST methods.
     * @param request servlet request
     * @param response servlet response
     */
    protected void processRequest(HttpServletRequest request, 
				 HttpServletResponse response)
            throws ServletException, IOException {
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        try {
            String userName = request.getParameter("txtUserName");
            String password = request.getParameter("txtPassword");
            
            out.println("Before Login"+"<br><br>");
            out.println("IsUserInRole?.." + request.isUserInRole("javaee6user")+"<br>");
            out.println("getRemoteUser?.." + request.getRemoteUser()+"<br>");
            out.println("getUserPrincipal?.." + request.getUserPrincipal()+"<br>");
            out.println("getAuthType?.." + request.getAuthType()+"<br><br>");
            
            try {
            request.login(userName, password); 
            }catch(ServletException ex) {
                out.println("Login Failed with a ServletException.." + 
						ex.getMessage());
                return;
            }
            out.println("After Login..."+"<br><br>");
            out.println("IsUserInRole?.." + request.isUserInRole("javaee6user")+"<br>");
            out.println("getRemoteUser?.." + request.getRemoteUser()+"<br>");
            out.println("getUserPrincipal?.." + request.getUserPrincipal()+"<br>");
            out.println("getAuthType?.." + request.getAuthType()+"<br><br>");
            
            request.logout();
            out.println("After Logout..."+"<br><br>");
            out.println("IsUserInRole?.." + request.isUserInRole("javaee6user")+"<br>");
            out.println("getRemoteUser?.." + request.getRemoteUser()+"<br>");
            out.println("getUserPrincipal?.." + request.getUserPrincipal()+"<br>");
            out.println("getAuthType?.." + request.getAuthType()+"<br>");
            
            
        } finally {
            out.close();
        }
    }

       /** 
     * Handles the HTTP <code>GET</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Handles the HTTP <code>POST</code> method.
     * @param request servlet request
     * @param response servlet response
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        processRequest(request, response);
    }

    /** 
     * Returns a short description of the servlet.
     */
    public String getServletInfo() {
        return "Short description";
    }
}

This servlet displays the name of the user who is currently logged in, then prompts a user for login, and prints out the information again, then logs out the user and prints the information again in order to demonstrate the effect of the login and logout methods. The application deployment descriptor, web.xml, includes a login-config element that specifies basic authentication. The runtime deployment descriptor, sun-web.xml, includes a role-mapping of the user of the application to a group of the same name on the Enterprise Server.

Declaring and Linking Role References

A security role reference defines a mapping between the name of a role that is called from a web component using isUserInRole(String role) and the name of a security role that has been defined for the application. If no <security-role-ref> element is declared in a deployment descriptor, and the isUserInRole method is called, the container defaults to checking the provided role name against the list of all security roles defined for the web application. Using the default method instead of using the security-role-ref element limits your flexibility to change role names in an application without also recompiling the servlet making the call.

The security-role-ref element is used when an application uses the HttpServletRequest.isUserInRole(String role) method. The value passed to the isUserInRole method is a String representing the role name of the user. The value of the role-name element must be the String used as the parameter to the HttpServletRequest.isUserInRole(String role) method. The role-link must contain the name of one of the security roles defined in the security-role elements. The container uses the mapping of security-role-ref to security-role when determining the return value of the call.

For example, to map the security role reference cust to the security role with role name bankCustomer, the syntax would be:

<servlet>
...
    <security-role-ref>
        <role-name>cust</role-name>
        <role-link>bankCustomer</role-link>
    </security-role-ref>
...
</servlet>

In this case, if the servlet called by a user belonging to the bankCustomer security role made the API call, isUserInRole("cust") would return true.

The <role-link> element in the security-role-ref element must match a <role-name> defined in the <security-role> element of the same web.xml deployment descriptor, as shown here:

<security-role>
    <role-name>bankCustomer</role-name>
</security-role>

A security role reference, including the name defined by the reference, is scoped to the component whose deployment descriptor contains the security-role-ref deployment descriptor element.

Using Message Security with Web Applications

Web Services Security: SOAP Message Security (WS-Security) is an international standard for interoperable Web Services Security that was collaboratively developed in OASIS by all the major providers of web services technology (including Sun Microsystems). WS-Security is a message security mechanism that uses XML Encryption and XML Digital Signature to secure web services messages sent over SOAP. The WS-Security specification defines the use of various security tokens including X.509 certificates, SAML assertions, and username/password tokens to authenticate and encrypt SOAP web services messages. The WS-Security specification can be viewed at http://www.oasis-open.org/committees/download.php/3281/WSS-SOAPMessageSecurity-17-082703-merged.pdf

WS-Security incorporates security features in the header of a SOAP message, working in the application layer. Message security differs from transport layer security (which is what is discussed in this chapter) in that message security can be used to decouple message protection from message transport so that messages remain protected after transmission, ensuring end-to-end security.

Sun's implementation of WS-Security is part of Metro, a web service stack. In the past, web services have relied on transport-based security such as SSL to provide point-to-point security. Metro implements the WS-Security specification to provide interoperable message content integrity and confidentiality, even in the presence of intermediaries. Metro also provides an implementation of the WS-Trust specification as a means for issuing, renewing, and validating security tokens used by WS-Security, and to establish and broker trust relationships. That portion of Metro is known as WSIT (Web Services Interoperability Technologies). Metro's WSIT subsystem is an implementation of a number of open web services specifications to support enterprise features. In addition to security, reliable messaging, and atomic transactions, Metro includes a bootstrapping and configuration technology.

Message security is not part of the Java EE 6 platform, but can be used with and by Java EE 6 applications by following the instructions from the Metro User's Guide at https://metro.dev.java.net/guide/.

Examples: Securing Web Applications

There is some basic setup required before any of the example applications will run correctly. Refer to Setting Up Your System for Running the Security Examples to make sure you have completed these steps prior to continuing with the examples.

The following examples use annotations, programmatic security, and/or declarative security to demonstrate adding security to existing web applications:

Here are some links to other locations where you will find examples of securing different types of applications:

Setting Up Your System for Running the Security Examples

To set up your system for running the security examples, you basically need to configure a user database that can be used by the application for authenticating users. Here are the steps you need to complete before continuing:

Example: Basic Authentication with a Servlet

This example discusses how to use basic authentication with a servlet. With basic authentication of a servlet, the web browser presents a standard login dialog that is not customizable. When a user submits their name and password, the server determines if the user name and password are those of an authorized user and sends the requested web resource if the user is authorized to view it.

    In general, the following steps are necessary for adding basic authentication to an unsecured servlet, such as the one described in Chapter 3, Getting Started with Web Applications. In the example application included with this tutorial, many of these steps have been completed for you and are listed here simply to show what needs to be done should you wish to create a similar application. The completed version of this example application can be found in the directory tut-install/examples/web/hello2_basicauth/.

  1. Follow the steps in Setting Up Your System for Running the Security Examples.

  2. Create a web module as described in Chapter 3, Getting Started with Web Applications for the servlet example, hello2.

  3. Add the appropriate security elements to the web.xml deployment descriptor. The deployment descriptor for the example application can be viewed at tut-install/examples/web/hello2_basicauth/web/WEB-INF/web.xml. The security elements are described in Specifying Security in the Deployment Descriptor.

  4. Build, package, and deploy the web application by following the steps in Building, Packaging, and Deploying the Servlet Basic Authentication Example Using NetBeans IDE or Building, Packaging, and Deploying the Servlet Basic Authentication Example Using Ant.

  5. Run the web application by following the steps described in Running the Basic Authentication Servlet.

  6. If you have any problems running this example, refer to the troubleshooting tips in Troubleshooting the Basic Authentication Example.

Specifying Security in the Deployment Descriptor

The elements of the deployment descriptor that add basic authentication to this example tells the server or browser to perform the following tasks:

Deployment descriptors elements are described in Introduction to Web Application Deployment Descriptors.

The following sample code shows the security elements for the deployment descriptor used in this example of basic authentication, which can be found in tut-install/examples/web/hello2_basicauth/web/WEB-INF/web.xml.

    <security-constraint>
        <display-name>SecurityConstraint</display-name>
        <web-resource-collection>
             <web-resource-name>WRCollection</web-resource-name>
            <url-pattern>/greeting</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>TutorialUser</role-name>
        </auth-constraint>
        <user-data-constraint>
             <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>file</realm-name>
    </login-config>
		<security-role>
			<role-name>TutorialUser</role-name>
		</security-role>

This deployment descriptor shows that all the request URI /greeting can only be accessed by users who have entered their user name and password and have been authorized to access this URL because they have been verified to be in the role TutorialUser. The data will be sent over a protected transport in order to keep the user name and password data from being read in transit.

Building, Packaging, and Deploying the Servlet Basic Authentication Example Using NetBeans IDE

    To build, package, and deploy the web/hello2_basicauth example application using NetBeans IDE, follow these steps:

  1. Follow the steps in Setting Up Your System for Running the Security Examples.

  2. Open the project in NetBeans IDE by selecting File->Open Project.

  3. Browse to the tut-install/examples/web/hello2_basicauth/ directory.

  4. Make sure that Open as Main Project is selected.

  5. Select Open Project.

  6. Right-click hello2_basicauth in the Projects pane, then select Clean and Build.

  7. Right-click hello2_basicauth in the Projects pane, then select Deploy.

  8. To run the servlet, follow the steps in Running the Basic Authentication Servlet.

Building, Packaging, and Deploying the Servlet Basic Authentication Example Using Ant

    To build, package, and deploy the web/hello2_basicauth example using the Ant tool, follow these steps:

  1. Follow the steps in Setting Up Your System for Running the Security Examples.

  2. From a terminal window or command prompt, change to the tut-install/examples/web/hello2_basicauth/ directory.

  3. Build and package the web application by entering the following command at the terminal window or command prompt:


    ant
    
  4. To deploy the example using Ant, enter the following command at the terminal window or command prompt:


    ant deploy
    

    The deploy target in this case gives you an incorrect URL to run the application. To run the application, please use the URL shown in Running the Basic Authentication Servlet.

  5. To run the web application, follow the steps in Running the Basic Authentication Servlet.

Running the Basic Authentication Servlet

    To run the web client, follow these steps:

  1. Open a web browser.

  2. Enter the following URL in your web browser:

    https://localhost:8181/hello2_basicauth/greeting

    You may be prompted to accept the security certificate for the server. If so, accept the security certificate.

  3. A default login form displays. Enter a user name and password combination that corresponds to a user that has already been created in the file realm of the Enterprise Server and has been assigned to the group of TutorialUser.

    Basic authentication is case-sensitive for both the user name and password, so enter the user name and password exactly as defined for the Enterprise Server.

    The server returns the requested resource if all of the following conditions are met:

    • There is a user defined for the Enterprise Server with the user name you entered.

    • The user with the user name you entered has the password you entered.

    • The user name and password combination you entered is assigned to the group of TutorialUser on the Enterprise Server.

    • The role of TutorialUser, as defined for the application, is mapped to the group of TutorialUser, as defined for the Enterprise Server.

    When these conditions are met, and the server has authenticated the user, the application will display as shown in Figure 25–6.

  4. Enter your name and click the Submit button. Because you have already been authorized, the name you enter in this step does not have any limitations. You have unlimited access to the application now.

    The application responds by saying “Hello” to you, as shown in Figure 25–7.

Figure 25–6 Running the Application

Screen shot of running basic authentication example showing
text field for user to type name

Figure 25–7 The Running Basic Authentication Response

Screen shot of running basic authentication example showing
response


Note –

For repetitive testing of this example, you may need to close and reopen your browser. You should also run the ant clean and ant undeploy targets or the NetBeans IDE Clean and Build option to get a fresh start.


Troubleshooting the Basic Authentication Example

    When doing iterative development with this web application, follow these steps if you are using NetBeans IDE:

  1. Close your web browser.

  2. Clean and recompile the files from the previous build by right-clicking hello2_basicauth and selecting Clean and Build.

  3. Redeploy the application by right-clicking hello2_basicauth and selecting Undeploy and Deploy.

  4. Open your web browser and reload the following URL:

    https://localhost:8181/hello2_basicauth/greeting

    Follow these steps if you are using the Ant tool:

  1. Close your web browser.

  2. Undeploy the web application. To undeploy the application, use the following command in the directory:


    ant undeploy
    
  3. Clean out files from the previous build, using the following command:


    ant clean
    
  4. Recompile, repackage, and redeploy the application, using the following commands:


    ant 
    ant deploy
    
  5. Open your web browser and reload the following URL:

    https://localhost:8181/hello2_basicauth/greeting

Example: Basic Authentication with JAX-WS

This section discusses how to configure a JAX-WS-based web service for HTTP basic authentication. When a service that is constrained by HTTP basic authentication is requested, the server requests a user name and password from the client and verifies that the user name and password are valid by comparing them against a database of authorized users.

For this tutorial, you will add the security elements to the JAX-WS service; build, package, and deploy the service; and then build and run the client application.

This example does not include a finished application, but provides instructions in the event that you want to secure a JAX-WS web service, such as the one that can be found in the directory tut-install/examples/jaxws/helloservice and is discussed in Creating a Simple Web Service and Client with JAX-WS. You build on this simple application by adding the necessary elements to secure the application using basic authentication.

    In general, the following steps are necessary to add basic authentication to a JAX-WS web service.

  1. Create an application like the one in Creating a Simple Web Service and Client with JAX-WS.

  2. Follow the steps in Setting Up Your System for Running the Security Examples.

  3. Add security elements that specify that basic authentication is to be performed to the application deployment descriptor, web.xml. This step is discussed in Adding Security Elements to the Deployment Descriptor.

  4. Build, package, and deploy the web service. See Building and Deploying helloservice with Basic Authentication Using NetBeans IDE or Building and Deploying helloservice with Basic Authentication Using Ant for the steps to accomplish this.

  5. Build and run the client application. See Building and Running the helloservice Client Application with Basic Authentication Using NetBeans IDE or Building and Running the helloservice Client Application with Basic Authentication Using Ant for the steps to accomplish this.

Adding Security Elements to the Deployment Descriptor

To enable basic authentication for the service, add security elements to the application deployment descriptor, web.xml. The security elements that need to be added to the deployment descriptor include the <security-constraint>, <login-config>, and <security-role> elements. These security elements are discussed in more detail in Introduction to Web Application Deployment Descriptors and in the Java Servlet Specification. The code is added to the original deployment descriptor to enable HTTP basic authentication. The resulting deployment descriptor looks like this:

<?xml version="1.0" encoding="UTF-8"?><web-app
     xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema"
     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>HelloService</display-name>
    <listener>
        <listener-class>
            com.sun.xml.ws.transport.http.servlet.WSServletContextListener
        </listener-class>
    </listener>
    <servlet>
        <display-name>HelloService</display-name>
        <servlet-name>HelloService</servlet-name>
        <servlet-class>com.sun.xml.ws.transport.http.servlet.WSServlet</servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>HelloService</servlet-name>
        <url-pattern>/hello</url-pattern>
    </servlet-mapping>
    <session-config>
        <session-timeout>30</session-timeout>
    </session-config>
    <security-constraint>
        <display-name>SecurityConstraint</display-name>
        <web-resource-collection>
             <web-resource-name>WRCollection</web-resource-name>
            <url-pattern>/hello</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>TutorialUser</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    <login-config>
        <auth-constraint>BASIC</auth-constraint>
        <realm-name>file</realm-name>
    </login-config>
		<security-role>
			<role-name>TutorialUser</role-name>
		</security-role>
</web-app>

This security constraint protects resources at the URI /hello. Anyone who tries to access this resource will be prompted for their user name and password and must be authenticated by the Enterprise Server before they will be granted access to the resource. The request is sent over a protected transport to ensure that the username and password are not intercepted in transit.

Building and Deploying helloservice with Basic Authentication Using NetBeans IDE

    To build, package, and deploy the example using NetBeans IDE, follow these steps, or the steps described in Building, Packaging, and Deploying the Service.

  1. Follow the steps in Setting Up Your System for Running the Security Examples.

  2. In NetBeans IDE, select File->Open Project.

  3. In the Open Project dialog, navigate to the project.

  4. Click Open Project.

  5. In the Projects tab, right-click the project and select Clean and Build.

  6. In the Projects tab, right-click the project and select Deploy.

    This step builds and packages the application into a WAR file, and deploys this war file to your Enterprise Server instance.

Building and Deploying helloservice with Basic Authentication Using Ant

    To build, package, and deploy the project using the Ant tool, follow these steps, or the steps described in Building, Packaging, and Deploying the Service.

  1. Follow the steps in Setting Up Your System for Running the Security Examples.

  2. From a terminal window or command prompt, go to the project directory.

  3. Build, package, and deploy the JAX-WS service by entering the following at the terminal window or command prompt in the project directory:


    ant all
    

You can test the service in the Admin Console. For more information on how to do this, read Testing the Service without a Client.

Building and Running the helloservice Client Application with Basic Authentication Using NetBeans IDE

    To build and run the client application using NetBeans IDE, follow these steps. The service must be deployed onto the Enterprise Server before compiling the client files. For information on deploying the service, read Building and Deploying helloservice with Basic Authentication Using NetBeans IDE.

  1. In NetBeans IDE, select File->Open Project.

  2. In the Open Project dialog, navigate to the project.

  3. Click Open Project.

  4. In the Projects tab, right-click the project and select Clean and Build.

  5. In the Projects tab, right-click the project and select Run.

    You will be prompted for your user name and password.

  6. Enter the user name and password of a user that has been entered into the database of users for the file realm and has been assigned to the group of TutorialUser.

    If the username and password you enter are authorized, you will see the output of the application client in the Output pane.

Building and Running the helloservice Client Application with Basic Authentication Using Ant

    To build and run the client application using the Ant tool, follow these steps. The secured service must be deployed onto the Enterprise Server before you can successfully compile the client application. For more information on deploying the service, read Building and Deploying helloservice with Basic Authentication Using Ant.

  1. Build the client by changing to the project directory and entering the following at the terminal window or command prompt:


    ant
    

    This command calls the default target, which builds and packages the application into a JAR file.

  2. Run the client by entering the following at the terminal window or command prompt:


    ant run
    

    A Login for User dialog displays.

  3. Enter a user name and password that correspond to a user set up on the Enterprise Server with a group of TutorialUser. Click OK.

Example: Form-Based Authentication with a Servlet

This example discusses how to use form-based authentication with a basic servlet. With form-based authentication, you can customize the login screen and error pages that are presented to the web client for authentication of their user name and password. When a user submits their name and password, the server determines if the user name and password are those of an authorized user and, if authorized, sends the requested web resource.

In general, the steps are necessary for adding form-based authentication to an unsecured servlet are similar to those described in Example: Basic Authentication with a Servlet, so just follow all of the steps in Example: Basic Authentication with a Servlet, except use the deployment descriptor described in Specifying Security in the Deployment Descriptor instead and create the login form and login error form pages as described in Creating the Login Form and the Error Page. The completed version of this example application can be found in the directory tut-install/examples/web/hello2_formauth/.

Creating the Login Form and the Error Page

When using form-based login mechanisms, you must specify a page that contains the form you want to use to obtain the user name and password, as well as which page to display if login authentication fails. This section discusses the login form and the error page used in this example. The section Specifying Security in the Deployment Descriptor shows how you specify these pages in the deployment descriptor.

The login page can be an HTML page, a JSP page, or a servlet, and it must return an HTML page containing a form that conforms to specific naming conventions (see the Java Servlet 3.0 specification for more information on these requirements). To do this, include the elements that accept user name and password information between <form></form> tags in your login page. The content of an HTML page, JSP page, or servlet for a login page should be coded as follows:

<form method=post action="j_security_check" >
    <input type="text"  name= "j_username" >
    <input type="password"  name= "j_password" >
</form>

The full code for the login page used in this example can be found at tut-install/examples/web/hello2_formauth/web/loginform.html. An example of the running login form page is shown later in Figure 25–8. Here is the code for this page:

<html>
<head>
    <title>Login Page</title>
</head>

<h2>Hello, please log in:</h2>
<br><br>
<form action="j_security_check" method=post>
    <p><strong>Please Enter Your User Name: </strong>
    <input type="text" name="j_username" size="25">
    <p><p><strong>Please Enter Your Password: </strong>
    <input type="password" size="15" name="j_password">
    <p><p>
    <input type="submit" value="Submit">
    <input type="reset" value="Reset">
</form>
</html>

The login error page is displayed if the user enters a user name and password combination that is not authorized to access the protected URI. For this example, the login error page can be found at tut-install/examples/web/hello2_formauth/web/loginerror.html. For this example, the login error page explains the reason for receiving the error page and provides a link that will allow the user to try again. Here is the code for this page:

<html>
<head>
    <title>Login Error</title>
</head>
<body>
    <c:url var="url" value="/index.jsp"/>
    <h2>Invalid user name or password.</h2>

    <p>Please enter a user name or password that is authorized to access this 
    application. For this application, this means a user that has been created in the 
    <code>file</code> realm and has been assigned to the <em>group</em> of 
    <code>TutorialUser</code>.  Click here to <a href="${url}">Try Again</a></p>
</body>
</html>

Specifying Security in the Deployment Descriptor

This example takes a very simple servlet-based web application and adds form-based security to this application. All security for this example is declared in the deployment descriptor for the application. A security constraint is defined in the deployment descriptor that tells the server to send a login form to collect user data, verify that the user is authorized to access the application, and, if so, display the JSP page to the user.

Deployment descriptor elements are described in Introduction to Web Application Deployment Descriptors.

The following sample code shows the deployment descriptor used in this example of form-based login authentication, which can be found in tut-install/examples/web/hello2_formauth/web/WEB-INF/web.xml.

<!-- FORM-BASED LOGIN AUTHENTICATION EXAMPLE -->
<?xml version="1.0" encoding="UTF-8"?>
 <web-app xmlns="http://java.sun.com/xml/ns/javaee" version="2.5"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">

    <display-name>hello2_formauth</display-name>
       <servlet>
             <display-name>index</display-name>
            <servlet-name>index</servlet-name>
            <jsp-file>/index.jsp</jsp-file>
      </servlet>
     <security-constraint>
             <display-name>SecurityConstraint</display-name>
            <web-resource-collection>
                  <web-resource-name>WRCollection</web-resource-name>
                 <url-pattern>/*</url-pattern>
         </web-resource-collection>
            <auth-constraint>
                  <role-name>TutorialUser</role-name>
            </auth-constraint>
            <user-data-constraint>
                <transport-guarantee>CONFIDENTIAL</transport-guarantee>
            </user-data-constraint>
       </security-constraint>
      <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>
     <security-role>
        <role-name>TutorialUser</role-name>
    </security-role>
</web-app>

Building, Packaging, and Deploying the Form-Based Authentication Example Using NetBeans IDE

    To build, package, and deploy this application using NetBeans IDE, follow these steps:

  1. Follow the steps in Setting Up Your System for Running the Security Examples.

  2. Open the project in NetBeans IDE by selecting File->Open Project.

  3. Browse to the tut-install/examples/web/hello2_formauth/ directory.

  4. Make sure that Open as Main Project is selected.

  5. Select Open Project.

  6. Right-click hello2_formauth in the Projects pane, then select Clean and Build.

  7. Right-click hello2_formauth in the Projects pane, then select Deploy.

  8. Follow the steps in Testing the Form-Based Authentication Web Client.

Building, Packaging, and Deploying the Form-Based Authentication Example Using Ant

    To build, package, and deploy this application using the Ant tool, follow these steps:

  1. Follow the steps in Setting Up Your System for Running the Security Examples.

  2. From a terminal window or command prompt, change to the tut-install/examples/web/hello2_formauth/ directory.

  3. Enter the following command at the terminal window or command prompt:


    ant
    

    This target will spawn any necessary compilations, copy files to the tut-install/examples/web/hello2_formauth/build/ directory, create the WAR file, and copy it to the tut-install/examples/web/hello2_formauth/dist/ directory.

  4. Deploy the WAR named hello2_formauth.war onto the Enterprise Server using Ant by entering the following command at the terminal window or command prompt:


    ant deploy
    
  5. Follow the steps in Testing the Form-Based Authentication Web Client.

Testing the Form-Based Authentication Web Client

    To run the web client, follow these steps:

  1. Open a web browser.

  2. Enter the following URL in your web browser:

    https://localhost:8181/hello2_formauth

    The login form displays in the browser, as shown in Figure 25–8.

  3. Enter a user name and password combination that corresponds to a user that has already been created in the file realm of the Enterprise Server and has been assigned to the group of TutorialUser.

  4. Click the Submit button. Form-based authentication is case-sensitive for both the user name and password, so enter the user name and password exactly as defined for the Enterprise Server.

    If you entered My_Name as the name and My_Pwd for the password, the server returns the requested resource if all of the following conditions are met:

    • There is a user defined for the Enterprise Server with the user name of My_Name.

    • The user with the user name of My_Name has a password of My_Pwd defined for the Enterprise Server.

    • The user My_Name with the password My_Pwd is assigned to the group of TutorialUser on the Enterprise Server.

    • The role of TutorialUser, as defined for the application, is mapped to the group of TutorialUser, as defined for the Enterprise Server.

      When these conditions are met, and the server has authenticated the user, the application will display as shown in Figure 25–9.

  5. Enter your name and click the Submit button. Because you have already been authorized, the name you enter in this step does not have any limitations. You have unlimited access to the application now.

    The application responds by saying “Hello” to you, as shown in Figure 25–10.

For additional testing, close and reopen your browser, enter the application URL, and enter a username and password that are not authorized to see the login error page generated.

Figure 25–8 Form-Based Login Page

Screen shot of form-based login page showing text fields
for user name and password

Figure 25–9 Running Web Application

Screen shot of running form-based web application with
text field for user to type name

Figure 25–10 The Running Form-Based Authentication Example

Screen shot of running form-based web application showing
response


Note –

For repetitive testing of this example, you may need to close and reopen your browser. You should also run the ant clean and ant undeploy commands to ensure a fresh build if using the Ant tool, or select Clean and Build then Undeploy and Deploy if using NetBeans IDE.