The Java EE 5 Tutorial

Chapter 30 Securing Web Applications

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 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.

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

Some of the material in this chapter assumes that you have already read Chapter 28, Introduction to Security in the Java EE Platform. This chapter also assumes that you are familiar with the web technologies discussed in Chapter 3, Getting Started with Web Applications, Chapter 5, JavaServer Pages Technology, and Chapter 10, JavaServer Faces Technology.

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, JSP pages, JSF pages, or web service endpoints. The interaction between a web client and a web application is illustrated in Figure 30–1.

Figure 30–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. This chapter provides more information on configuring security for web applications.

For secure transport, most web applications use the HTTPS protocol. For more information on using the HTTPS protocol, read Establishing a Secure Connection Using SSL.

Working with Security Roles

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

Declaring Security Roles

You can declare security role names used in web applications using either the @DeclareRoles annotation (preferred) or the security-role-ref elements of the deployment descriptor. Declaring security role names in this way enables you to link the security role names used in the code to the security roles defined for an assembled application. In the absence of this linking step, any security role name used in the code will be assumed to correspond to a security role of the same name in the assembled application.

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

You can also use the security-role-ref elements for those references that were declared in annotations and you want to have linked to a security-role whose name differs from the reference value. If a security role reference is not linked to a security role in this way, the container must map the reference name to the security role of the same name. See Declaring and Linking Role References for a description of how security role references are linked to security roles.

For an example using each of these methods, read the following sections:

Specifying Security Roles Using Annotations

Annotations are the best way to define security roles on a class or a method. The @DeclareRoles annotation is used to define the security roles that comprise the security model of the application. This annotation is specified on a class, and it typically would be used to define roles that could be tested (for example, by calling isUserInRole) from within the methods of the annotated class.

Following is an example of how this annotation would be used. In this example, employee is the only security role specified, but the value of this parameter can include a list of security roles specified by the application.

@DeclareRoles("employee")
public class CalculatorServlet {
    //...
}

Specifying @DeclareRoles("employee") is equivalent to defining the following in the web.xml:

<security-role>
    <role-name>employee</role-name>
</security-role>

This annotation is not used to link application roles to other roles. When such linking is necessary, it is accomplished by defining an appropriate security-role-ref in the associated deployment descriptor, as described in Declaring and Linking Role References.

When a call is made to isUserInRole from the annotated class, the caller identity associated with the invocation of the class is tested for membership in the role with the same name as the argument to isUserInRole. If a security-role-ref has been defined for the argument role-name, the caller is tested for membership in the role mapped to the role-name.

Specifying Security Roles Using Deployment Descriptor Elements

The following snippet of a deployment descriptor is taken from the simple sample application. This snippet includes all of the elements needed to specify security roles using deployment descriptors:

<servlet>
     ...
    <security-role-ref>
        <role-name>MGR</role-name>
        <!-- role name used in code -->
        <role-link>employee</role-link>
    </security-role-ref>
</servlet>

<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>role1</role-name>
        <role-name>employee</role-name>
    </auth-constraint>
</security-constraint>

 <!-- Security roles referenced by this web application -->
<security-role>
    <role-name>role1</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: role1 and employee. This enables the deployer to map all of the roles defined in the application to users and groups defined on the Application Server.

The auth-constraint element specifies the roles (role1, employee) that can access HTTP methods (PUT, DELETE, GET, POST) located in the directory specified by the url-pattern element (/jsp/security/protected/*). You could also have used the @DeclareRoles annotation in the source code to accomplish this task.

The security-role-ref element is used when an application uses the HttpServletRequest.isUserInRole(String role) method. 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.

Mapping Security Roles to Application Server Groups

To map security roles to application server principals and groups, use the security-role-mapping element in the runtime deployment descriptor (DD). 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 Application Server’s resources. The Application Server web application runtime DD is located in /WEB-INF/ along with the web application DD. 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:

<sun-web-app>

      <security-role-mapping>
        <role-name>CEO</role-name>
        <principal-name>smcneely</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. The role-name element 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 the @DeclareRoles annotation.

Sometimes the role names used in the application are the same as the group names defined on the Application Server. Under these circumstances, you can use the Admin Console to define a default principal to role mapping that apply to the entire Application 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 Java System Application Server 9.1 Developer’s Guide or Sun Java System Application Server 9.1 Administration Guide.

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.

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

The following is a code snippet from an index.jsp file that uses these methods to access security information about the component’s caller.

<%@ taglib prefix="fmt" uri="http://java.sun.com/jstl/fmt" %>
<fmt:setBundle basename="LocalStrings"/>

<html>
<head>
<title><fmt:message key="index.jsp.title"/>/title>
</head>
<body bgcolor="white">

<fmt:message key="index.jsp.remoteuser"/> 
<b><%= request.getRemoteUser() %>
</b><br><br>

<%
    if (request.getUserPrincipal() != null) {
%>
    <fmt:message key="index.jsp.principal"/> <b>
<%= request.getUserPrincipal().getName() %></b><br><br>
<%
    } else {
%>
    <fmt:message key="index.jsp.noprincipal"/>
<%
    }
%>

<%
    String role = request.getParameter("role");
    if (role == null)
        role = "";
    if (role.length() > 0) {
        if (request.isUserInRole(role)) {
%>
            <fmt:message key="index.jsp.granted"/> <b><%= role %></b><br><br>
<%
        } else {
%>
            <fmt:message key="index.jsp.notgranted"/> <b><%= role %></b><br><br>
<%
        }
    }
%>

<fmt:message key="index.jsp.tocheck"/>
<form method="GET">
<input type="text" name="role" value="<%= role %>">
</form>

</body>
</html>

Declaring and Linking Role References

A security role is an application-specific logical grouping of users, classified by common traits such as customer profile or job title. When an application is deployed, these roles are mapped to security identities, such as principals (identities assigned to users as a result of authentication) or groups, in the runtime environment. Based on this mapping, a user with a certain security role has associated access rights to a web application.

The value passed to the isUserInRole method is a String representing the role name of the user. 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 a <security-role-ref> element is not 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.

For example, during application assembly, the assembler creates security roles for the application and associates these roles with available security mechanisms. The assembler then resolves the security role references in individual servlets and JSP pages by linking them to roles defined for the application. For example, the assembler could map the security role reference cust to the security role with the role name bankCustomer using the <security-role-ref> element of the deployment descriptor.

Declaring Roles Using Annotations

The preferred method of declaring roles referenced in an application is to use the @DeclareRoles annotation. The following code sample provides an example that specifies that the roles of j2ee and guest will be used in the application, and verifies that the user is in the role of j2ee before printing out Hello World.

import java.io.IOException;
import java.io.PrintWriter;

import javax.annotation.security.DeclareRoles;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@DeclareRoles({"j2ee", "guest"})
public class Servlet extends HttpServlet {

    public void service(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setContentType("text/html");
        PrintWriter out = resp.getWriter();

        out.println("<HTML><HEAD><TITLE>Servlet Output</TITLE>
            </HEAD><BODY>");
         if (req.isUserInRole("j2ee") && !req.isUserInRole("guest")) {
            out.println("Hello World");
        } else {
            out.println("Invalid roles");
        }
        out.println("</BODY></HTML>");
    }
}

Declaring Roles Using Deployment Descriptor Elements

An example of declaring roles referenced in an application using deployment descriptor elements is shown in the following web.xml deployment descriptor snippet:

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

When you use the isUserInRole(String role) method, the String role is mapped to the role name defined in the <role-name> element nested within the <security-role-ref> element. The <role-link> element in the web.xml deployment descriptor must match a <role-name> defined in the <security-role> element of the web.xml deployment descriptor, as shown here:

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

Defining Security Requirements for 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 declaratively by use of the deployment descriptor mechanism or programmatically by 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 whether or not to use HTTPS for transport. If you don’t define security requirements, the deployer will have to determine the security requirements independently.

If you specify a value in an annotation, and then explicitly specify the same value in the deployment descriptor, the value in the deployment descriptor overrides any values specified in annotations. If a value for a servlet has not been specified in the deployment descriptor, and a value has been specified for that servlet by means of the use of annotations, the value specified in annotations will apply. The granularity of overriding is on the per-servlet basis.

The web application deployment descriptor may contain an attribute of metadata-complete on the web-app element. The metadata-complete attribute defines whether the web application deployment descriptor is complete, or whether the class files of the JAR file should be examined for annotations that specify deployment information. When the metadata-complete attribute is not specified, or is set to false, the deployment descriptors examine the class files of applications for annotations that specify deployment information. When the metadata-complete attribute is set to true, the deployment descriptor ignores any servlet annotations present in the class files of the application. Thus, deployers can use deployment descriptors to customize or override the values specified in annotations.

Many elements for security in a web application deployment descriptor cannot, as yet, be specified as annotations, therefore, for securing web applications, deployment descriptors are a necessity. However, where possible, annotations are the recommended method for securing web components.

The following sections discuss the use of annotations and deployment descriptor elements to secure web applications:

Declaring Security Requirements Using Annotations

The Java Metadata Specification (JSR-175), which is part of J2SE 5.0 and greater, provides a means of specifying configuration data in Java code. Metadata in Java code is more commonly referred to in this document as annotations. In Java EE, annotations are used to declare dependencies on external resources and configuration data in Java code without the need to define that data in a configuration file. Several common annotations are specific to specifying security in any Java application. These common annotations are specified in JSR-175, A Metadata Facility for the Java Programming Language, and JSR-250, Common Annotations for the Java Platform. Annotations specific to web components are specified in the Java Servlet 2.5 Specification.

In servlets, you can use the annotations discussed in the following sections to secure a web application:

Using the @DeclareRoles Annotation

This annotation is used to define the security roles that comprise the security model of the application. This annotation is specified on a class, and it typically would be used to define roles that could be tested (for example, by calling isUserInRole) from within the methods of the annotated class.

Following is an example of how this annotation would be used. In this example, BusinessAdmin is the only security role specified, but the value of this parameter can include a list of security roles specified by the application.

@DeclareRoles("BusinessAdmin")
public class CalculatorServlet {
    //...
}

Specifying @DeclareRoles("BusinessAdmin") is equivalent to defining the following in web.xml:

<web-app>
    <security-role>
        <role-name>BusinessAdmin</role-name>
    </security-role>
</web-app>

The syntax for declaring more than one role is as shown in the following example:

@DeclareRoles({"Administrator", "Manager", "Employee"})

This annotation is not used to link application roles to other roles. When such linking is necessary, it is accomplished by defining an appropriate security-role-ref in the associated deployment descriptor, as described in Declaring and Linking Role References.

When a call is made to isUserInRole from the annotated class, the caller identity associated with the invocation of the class is tested for membership in the role with the same name as the argument to isUserInRole. If a security-role-ref has been defined for the argument role-name, the caller is tested for membership in the role mapped to the role-name.

For further details on the @DeclareRoles annotation, refer to JSR–250, Common Annotations for the Java Platform, and Using Enterprise Bean Security Annotations in this tutorial.

Using the @RunAs Annotation

The @RunAs annotation defines the role of the application during execution in a Java EE container. It can be specified on a class, allowing developers to execute an application under a particular role. The role must map to the user/group information in the container’s security realm. The value element in the annotation is the name of a security role of the application during execution in a Java EE container. The use of the @RunAs annotation is discussed in more detail in Propagating Security Identity.

The following is an example that uses the @RunAs annotation:

@RunAs("Admin")
public class CalculatorServlet {
@EJB private ShoppingCart myCart;
    public void doGet(HttpServletRequest, req, HttpServletResponse res) {
        //....
        myCart.getTotal();
        //....
    }
}
//....
}

The @RunAs annotation is equivalent to the run-as element in the deployment descriptor.

Declaring Security Requirements in a Deployment Descriptor

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 declaratively by use of the deployment descriptor mechanism. A deployment descriptor enables an application’s security structure, including roles, access control, and authentication requirements, to be expressed in a form external to the application.

A web application is defined using a standard Java EE web.xml deployment descriptor. A deployment descriptor is an XML schema document that conveys elements and configuration information for web applications. The deployment descriptor must indicate which version of the web application schema (2.4 or 2.5) it is using, and the elements specified within the deployment descriptor must comply with the rules for processing that version of the deployment descriptor. Version 2.5 of the Java Servlet Specification, which can be downloaded at SRV.13, Deployment Descriptor, contains more information regarding the structure of deployment descriptors.

The following 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 section SRV.13.5.2, An Example of Security, from the Java Servlet Specification 2.5.

<?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>
        <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>
        <security-role-ref>
            <role-name>MGR</role-name>
            <!-- role name used in code -->
            <role-link>manager</role-link>
        </security-role-ref>
    </servlet>

    <!-- SECURITY ROLE -->
    <security-role>
        <role-name>manager</role-name>
    </security-role>

    <servlet-mapping>
        <servlet-name>catalog</servlet-name>
        <url-pattern>/catalog/*</url-pattern>
    </servlet-mapping>

    <!-- SECURITY CONSTRAINT -->
    <security-constraint>
        <web-resource-collection>
            <web-resource-name>CartInfo</web-resource-name>
            <url-pattern>/catalog/cart/*</url-pattern>
            <http-method>GET</http-method>
            <http-method>POST</http-method>
        </web-resource-collection>
        <auth-constraint>
            <role-name>manager</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
        </user-data-constraint>
    </security-constraint>

    <!-- LOGIN CONFIGURATION-->
    <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>
</web-app>

As shown in the preceding example, the <web-app> element is the root element for web applications. The <web-app> element contains the following elements that are used for specifying security for a web application:

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

The following sections provide more information on deployment descriptor security elements:

Specifying Security Constraints

Security constraints are a declarative way to define the protection of web content. A security constraint is used to define access privileges to a collection of resources using their URL mapping. Security constraints are defined in a deployment descriptor. The following example shows a typical security constraint, including all of the elements of which it consists:

<security-constraint>
    <display-name>ExampleSecurityConstraint</display-name>
    <web-resource-collection>
        <web-resource-name>
            ExampleWRCollection
        </web-resource-name>
        <url-pattern>/example</url-pattern>
        <http-method>POST</http-method>
        <http-method>GET</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>exampleRole</role-name>
    </auth-constraint>
    <user-data-constraint>
        <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
</security-constraint>

As shown in the example, a security constraint (<security-constraint> in deployment descriptor) consists of the following elements:

Security constraints work only on the original request URI and not on calls made throug a RequestDispatcher (which include <jsp:include> and <jsp:forward>). Inside the application, it is assumed that the application itself has complete access to all resources and would not forward a user request unless it had decided that the requesting user also had access.

Many applications feature unprotected web content, which any caller can access without authentication. In the web tier, you provide unrestricted access simply by not configuring a security constraint for that particular request URI. It is common to have some unprotected resources and some protected resources. In this case, you will define security constraints and a login method, but they will not be used to control access to the unprotected resources. Users won’t be asked to log in until the first time they enter a protected request URI.

The Java Servlet specification defines the request URI as the part of a URL after the host name and port. For example, let’s say you have an e-commerce site with a browsable catalog that you would want anyone to be able to access, and a shopping cart area for customers only. You could set up the paths for your web application so that the pattern /cart/* is protected but nothing else is protected. Assuming that the application is installed at context path /myapp, the following are true:

A user will not be prompted to log in until the first time that user accesses a resource in the cart/ subdirectory.

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 POST method of all resources with the URL pattern /acme/wholesale/*, and allow users with the role of CLIENT access to the POST method 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>
</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. Section 12.7.2 of the Java Servlet 2.5 Specification (downloadable from http://jcp.org/en/jsr/detail?id=154) gives an example that illustrates the combination of constraints and how the declarations will be interpreted.

Specifying a Secure Connection

A user data constraint (<user-data-constraint> in the deployment descriptor) requires that all constrained URL patterns and HTTP methods specified in the security constraint are received over a protected transport layer connection such as HTTPS (HTTP over SSL). A user data constraint specifies a transport guarantee (<transport-guarantee> in the deployment descriptor). The choices for transport guarantee include CONFIDENTIAL, INTEGRAL, or NONE. If you specify CONFIDENTIAL or INTEGRAL as a security constraint, 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 following security constraint includes a transport guarantee:

<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>

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 Application 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 Application Server can be found in Establishing a Secure Connection Using SSL and in the Sun Java System Application Server 9.1 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 an Authentication Mechanism

To specify an authentication mechanism for your web application, declare a login-config element in the application deployment descriptor. The login-config element is used to configure the authentication method and realm name that should be used for this application, and the attributes that are needed by the form login mechanism when form-based login is selected. The sub-element auth-method configures the authentication mechanism for the web application. The element content must be either BASIC, DIGEST, FORM, CLIENT-CERT, or a vendor-specific authentication scheme. The realm-name element indicates the realm name to use for the authentication scheme 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.

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, the user will not be authenticated.

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. To specify an authentication method, place the <auth-method> element between <login-config> elements in the deployment descriptor, like this:

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

An example of a deployment descriptor that constrains all web resources for this application (in italics below) and requires HTTP basic authentication when you try to access that resource (in bold below) is shown here:

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5"
         xmlns="http://java.sun.com/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
             http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
    <display-name>basicauth</display-name>
    <servlet>
        <display-name>index</display-name>
        <servlet-name>index</servlet-name>
        <jsp-file>/index.jsp</jsp-file>
    </servlet>
    <security-role>
        <role-name>loginUser</role-name>
    </security-role>
    <security-constraint>
        <display-name>SecurityConstraint1</display-name>
        <web-resource-collection>
            <web-resource-name>WRCollection</web-resource-name>
            <url-pattern>/*</url-pattern>
        </web-resource-collection>
        <auth-constraint>
            <role-name>loginUser</role-name>
        </auth-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
    </login-config>
</web-app>

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 Application Server and the Sun Java System Application Server 9.1 Administration Guide.

The authentication mechanisms are discussed further in the following sections:

HTTP Basic Authentication

    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. 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 30–2 shows what happens when you specify HTTP basic authentication.

Figure 30–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>
</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.

Example: Basic Authentication with JAX-WS is an example application that uses HTTP basic authentication in a JAX-WS service. Example: Using Form-Based Authentication with a JSP Page can be easily modified to demonstrate basic authentication. To do so, replace the text between the <login-config> elements with those shown in this section.

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 30–3 shows what happens when you specify form-based authentication.

Figure 30–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.

The section Example: Using Form-Based Authentication with a JSP Page 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>

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 30–4 shows what occurs during certificate-based mutual authentication.

Figure 30–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 30–5 shows what occurs during user name- and password-based mutual authentication.

Figure 30–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 user name and a password. However, the authentication is performed by transmitting the password in an encrypted form which is much more secure than the simple Base64 encoding used by basic authentication. Digest authentication is not currently in widespread use, and is not implemented in the Application Server, therefore, there is no further discussion of it in this document.

Examples: Securing Web Applications

There are several ways in which you can secure web applications. These include the following options:

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

The following examples demonstrate adding basic authentication to an EJB endpoint or enterprise bean:

Example: Using Form-Based Authentication with a JSP Page

This example discusses how to use form-based authentication with a basic JSP page. 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. If the topic of authentication is new to you, please refer to the section Specifying an Authentication Mechanism.

In general, the following steps are necessary for adding form-based authentication to an unsecured JSP page, such as the one described in Web Modules. 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/javaeetutorial5/examples/web/hello1_formauth/.

    The following steps describe how to set up your system for running the example applications, describe the sample application, and provide the steps for compiling, packaging, deploying, and testing the example application.

  1. If you have not already done so, set up your system so that the Ant tool and/or NetBeans IDE will run properly. To do this, follow the instructions in Building the Examples. This step is necessary to set the properties that are specific to your installation of the Application Server and Java EE 5 Tutorial.

  2. If you have not already done so, add an authorized user to the Application Server. For this example, add users to the file realm of the Application Server and assign the user to the group user. This topic is discussed more in Adding Authorized Roles and Users.

  3. Create a web module as described in Web Modules. The subsequent steps discuss adding security to this basic application. The resulting application is found in the directory tut-install/javaeetutorial5/examples/web/hello1_formauth/.

  4. Create the login form and login error form pages. Files for the example application can be viewed at tut-install/javaeetutorial5/examples/web/hello1_formauth/web. These pages are discussed in Creating the Login Form and the Error Page.

  5. Create a web.xml deployment descriptor and add the appropriate security elements (the application on which this section is based did not originally require a deployment descriptor.) The deployment descriptor for the example application can be viewed at tut-install/javaeetutorial5/examples/hello1_formauth/web/WEB-INF. The security elements for the web.xml deployment descriptor are described in Specifying a Security Constraint.

  6. Map the role name defined for this resource (loginUser) to a group of users defined on the Application Server. For more information on how to do this, read Mapping Application Roles to Application Server Groups.

  7. Build, package, deploy, and run the web application by following the steps in Building, Packaging, and Deploying the Form-Based Authentication Example Using NetBeans IDE or Building, Packaging, and Deploying the Form-Based Authentication Example Using Ant.

  8. Test the web client, following the steps in Testing the Form-Based Authentication Web Client.

Creating a Web Client for Form-Based Authentication

The web client in this example is a standard JSP page, and annotations are not used in JSP pages because JSP pages are compiled as they are presented to the browser. Therefore, none of the code that adds form-based authentication to the example is included in the web client. The code for the JSP page used in this example, hello1_formauth/web/index.jsp, is exactly the same as the code used for the unsecured JSP page from the example application at tut-install/javaeetutorial5/examples/web/hello1/web/index.jsp.

The information that adds form-based authentication to this example is specified in the deployment descriptor. This information is discussed in Specifying a Security Constraint.

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 a Security Constraint 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 2.5 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/javaeetutorial5/examples/web/hello1_formauth/web/logon.jsp. An example of the running login form page is shown later in Figure 30–6. 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/javaeetutorial5/examples/web/hello1_formauth/web/logonError.jsp. 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>user</code>.  Click here to <a href="${url}">Try Again</a></p>
</body>
</html>

Specifying a Security Constraint

This example takes a very simple JSP page-based web application and adds form-based security to this application. The JSP page is exactly the same as the JSP page used in the example described in Web Modules. 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.

If this client were a web service endpoint and not a JSP page, you could use annotations to declare security roles and to specify which roles were allowed access to which methods. However, there is no resource injection in JSP pages, so you cannot use annotations and must use the equivalent deployment descriptor elements.

Deployment descriptor elements are described in Declaring Security Requirements in a Deployment Descriptor.

The following sample code shows the deployment descriptor used in this example of form-based login authentication, which can be found in tut-install/javaeetutorial5/examples/web/hello1_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>hello1_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>loginUser</role-name>
            </auth-constraint>
            <user-data-constraint>
                <transport-guarantee>NONE</transport-guarantee>
            </user-data-constraint>
       </security-constraint>
      <login-config>
            <auth-method>FORM</auth-method>
         <form-login-config>
                  <form-login-page>/logon.jsp</form-login-page>
                 <form-error-page>/logonError.jsp</form-error-page>
          </form-login-config>
     </login-config>
     <security-role>
        <role-name>loginUser</role-name>
    </security-role>
</web-app>

More description of the elements that declare security in a deployment descriptor can be found in Specifying Security Constraints.

Protecting Passwords with SSL

Passwords are not protected for confidentiality with HTTP basic or form-based authentication, meaning that passwords sent between a client and a server on an unprotected session can be viewed and intercepted by third parties. To overcome this limitation, you can run these authentication protocols over an SSL-protected session and ensure that all message content is protected for confidentiality.

A <transport-guarantee> element indicates whether or not the protected resources should travel over protected transport. For simplicity, this example does not require protected transport, but in a real world application, you would want to set this value to CONFIDENTIAL to ensure that the user name and password are not observed during transmission. When running on protected transport, you can run the application over the secure SSL protocol, https, and specify the secure port where your SSL connector is created (the default for the Application Server is 8181). If you do not specify the HTTPS protocol, the server will automatically redirect the application to the secure port.

Adding Authorized Roles and Users

To authenticate a user and allow that user access to protected resources on the Application Server, you must link the roles defined in the application to the users defined for the Application Server.

When an application is deployed, the application-specific security roles are mapped to security identities in the runtime environment, such as principals (identities assigned to users as a result of authentication) or groups. Based on this mapping, a user who has been assigned a certain security role has associated access rights to a web application deployed onto a server.

As shown in the deployment descriptor for this example application, the security constraint specifies that users assigned to the role of loginUser are authorized to access any of the files in the hello1_formauth application. In this example, when a resource that is constrained by this same security constraint is accessed, for example, hello1_formauth/web/index.jsp, the Application Server sends the login form, receives the login information, and checks to see if the user is in a group that has been mapped to the role of loginUser. If the user name and password are those of an authorized user, access to the resource is granted to the requester.

    To set up users for this example application, follow these steps:

  1. Using the Admin Console, create a user in the file realm of the Application Server and assign that user to the group user. Make sure to note the user name and password that you enter in this step so that you can use it for testing the application later (these fields are case-sensitive). If you need help with the steps required to accomplish this task, read Managing Users and Groups on the Application Server for more information.

  2. Map the application security role of loginUser to the group of user that has been configured on the Application Server. For more information on how to do this mapping, read Mapping Application Roles to Application Server Groups.

Mapping Application Roles to Application Server Groups

Map the role of loginUser defined in the application to the group of user defined on the Application Server by adding a security-role-mapping element to the sun-web.xml runtime deployment descriptor file. To deploy a WAR on the Application Server, the WAR file must contain a runtime deployment descriptor. 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 Application Server’s resources.

The runtime deployment descriptor for this example, tut-install/javaeetutorial5/examples/web/hello1_formauth/web/WEB-INF/sun-web.xml, looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC 
"-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" 
"http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app>
    <context-root>/hello1_formauth
</context-root>
    <security-role-mapping>
        <role-name>loginUser</role-name>
        <group-name>user</group-name>
    </security-role-mapping>
</sun-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 instructions in Building the Examples if you have not already done so. This step is necessary to provide the Ant targets with the location of your tutorial and Application Server installations.

  2. Add users to the file realm of the Application Server as described in Adding Authorized Roles and Users if you have not already done so.

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

  4. Browse to the tut-install/javaeetutorial5/examples/web/hello1_formauth/ directory.

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

  6. Select Open Project.

  7. If you are prompted to regenerate the build-impl.xml file, select the Regenerate button.

  8. Right-click hello1_formauth in the Projects pane, then select Clean and Build.

  9. Right-click hello1_formauth in the Projects pane, then select Undeploy and Deploy.

  10. 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 instructions in Building the Examples if you have not already done so. This step is necessary to provide the Ant targets with the location of your tutorial and Application Server installations.

  2. Add users to the file realm of the Application Server as described in Adding Authorized Roles and Users if you have not already done so.

  3. From a terminal window or command prompt, change to the tut-install/javaeetutorial5/examples/web/hello1_formauth/ directory.

  4. 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/javaeetutorial5/examples/web/hello1_formauth/build/ directory, create the WAR file, and copy it to the tut-installjavaeetutorial5/examples/web/hello1_formauth/dist/ directory.

  5. Deploy the WAR named hello1_formauth.war onto the Application Server using Ant by entering the following command at the terminal window or command prompt:


    ant deploy
    
  6. 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:

    http://localhost:8080/hello1_formauth

    Note –

    If you set the transport guarantee to CONFIDENTIAL as discussed in Protecting Passwords with SSL, you must load the application in a web browser using https for the protocol, the HTTPS port that you specified during installation for the port (by default this port is 8181), and the context name for the application you wish to run. For the form-based authentication example, you could run the example using the following URL: https://localhost:8181/hello1_formauth.


    The login form displays in the browser, as shown in Figure 30–6.

  3. Enter a user name and password combination that corresponds to a user that has already been created in the file realm of the Application Server and has been assigned to the group of user, as discussed in Adding Authorized Roles and Users.

  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 Application 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 Application 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 Application Server.

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

    • The role of loginUser, as defined for the application, is mapped to the group of user, as defined for the Application Server.

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

  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 30–8.

Figure 30–6 Form-Based Login Page

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

Figure 30–7 Running Web Application

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

Figure 30–8 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.


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. If the topic of authentication is new to you, please refer to the section Specifying an Authentication Mechanism.

In general, the following steps are necessary for adding basic authentication to an unsecured servlet, such as the one described in Web Modules. 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/javaeetutorial5/examples/web/hello2_basicauth/.

    The following steps describe how to set up your system for running the example applications, describe the sample application, and provide the steps for compiling, packaging, deploying, and testing the example application.

  1. If you have not already done so, set up your system so that the Ant tool and/or NetBeans IDE will run properly. To do this, follow the instructions in Building the Examples. This step is necessary to set the properties that are specific to your installation of the Application Server and Java EE 5 Tutorial.

  2. If you have not already done so, add an authorized user to the Application Server. For this example, add users to the file realm of the Application Server and assign the user to the group user. This topic is discussed more in Adding Authorized Roles and Users.

  3. Create a web module as described in Web Modules for the servlet example, hello2. The subsequent steps discuss adding security to this basic application. The files for this example application are in tut-install/javaeetutorial5/examples/web/hello2_basicauth/.

  4. Declare the roles that will be used in this application. For this example, this is done by adding the @DeclareRoles annotation to GreetingServlet.java. This code is shown in Declaring Security Roles.

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

  6. Map the role name defined for this resource (helloUser) to a group of users defined on the Application Server. For more information on how to do this, read Mapping Application Roles to Application Server Groups.

  7. 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.

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

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

Declaring Security Roles

There are two annotations that can be used with servlets: @DeclareRoles and @RunAs. In this example, the @DeclareRoles annotation is used to specify which roles are referenced in this example.

The following section of the tut-install/javaeetutorial5/examples/web/hello2_basicauth/src/servlets/GreetingServlet.java file contains the code necessary to declare that the role of helloUser is used in this application:

package servlets;

import java.io.*;
import java.util.*;
import java.sql.*;
import javax.servlet.*;
import javax.servlet.http.*;
import javax.annotation.security.DeclareRoles;
/**
* This is a simple example of an HTTP Servlet that can only be accessed
* by an authenticated user.  It responds to the GET
* method of the HTTP protocol.
*/
@DeclareRoles("helloUser")
public class GreetingServlet extends HttpServlet {

    public void doGet (HttpServletRequest request,
        HttpServletResponse response)
            throws ServletException, IOException

You could also declare security roles using the <security-role> element in the deployment descriptor. If you prefer to declare security roles this way, read Declaring Roles Using Deployment Descriptor Elements.

Specifying the Security Constraint

This example takes a very simple servlet-based web application and adds basic authentication to this application. The servlet is basically the same as the servlet used in the example described in Web Modules, with the exception of the annotations added and discussed in Declaring Security Roles.

The security constraint for this example is declared in the application deployment descriptor. The security constraint tells the server or browser to perform the following tasks:

Deployment descriptors elements are described in Declaring Security Requirements in a Deployment Descriptor.

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/javaeetutorial5/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>helloUser</role-name>
        </auth-constraint>
        <user-data-constraint>
             <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    <login-config>
        <auth-method>BASIC</auth-method>
        <realm-name>file</realm-name>
    </login-config>

More description of the elements that declare security in a deployment descriptor can be found in Specifying Security Constraints.

Protecting Passwords with SSL

Passwords are not protected for confidentiality with HTTP basic or form-based authentication, meaning that passwords sent between a client and a server on an unprotected session can be viewed and intercepted by third parties. To overcome this limitation, you can run these authentication protocols over an SSL-protected session and ensure that all message content is protected for confidentiality.

A <transport-guarantee> element indicates whether or not the protected resources should travel over protected transport. For simplicity, this example does not require protected transport, but in a real world application, you would want to set this value to CONFIDENTIAL to ensure that the user name and password are not observed during transmission. When running on protected transport, you need to use the secure SSL protocol, https, and specify the secure port where your SSL connector is created (the default for the Application Server is 8181).

Adding Authorized Roles and Users

To authenticate a user and allow that user access to protected resources on the Application Server, you must link the roles defined in the application to the users defined for the Application Server.

When an application is deployed, the application-specific security roles are mapped to security identities in the runtime environment, such as principals (identities assigned to users as a result of authentication) or groups. Based on this mapping, a user who has been assigned a certain security role has associated access rights to a web application deployed onto a server.

As shown in the deployment descriptor for this example application, the security constraint specifies that users assigned to the role of helloUser are authorized to access the URL pattern /greeting. In this example, when this resource (because it is constrained by a security constraint) is accessed, the Application Server sends a default login dialog, receives the login information, and checks to see if the user is in a group that has been mapped to the role of helloUser. If the user name and password are those of an authorized user, access to the resource is granted to the requester.

    To set up users for this example application, follow these steps:

  1. If you have not already done so, create a user in the file realm of the Application Server and assign that user to the group user. Make sure to note the user name and password that you enter in this step so that you can use it for testing the application later. If you need help with the steps required to accomplish this task, read Managing Users and Groups on the Application Server for more information.

  2. Map the application security role of helloUser to the group of user that has been configured on the Application Server. For more information on how to do this mapping, read Mapping Application Roles to Application Server Groups.

Mapping Application Roles to Application Server Groups

Map the role of helloUser defined in the application to the group of user defined on the Application Server by adding a security-role-mapping element to the sun-web.xml runtime 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 Application Server’s resources.

The runtime deployment descriptor for this example, tut-install/javaeetutorial5/examples/web/hello2_basicauth/web/WEB-INF/sun-web.xml, looks like this:

<sun-web-app>
    <context-root>/hello2_basicauth</context-root>
    <security-role-mapping>
        <role-name>helloUser</role-name>
        <group-name>user</group-name>
    </security-role-mapping>
</sun-web-app>

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. If you have not already done so, follow the instructions in Building the Examples. This step is necessary to provide the Ant targets with the location of your tutorial and Application Server installations.

  2. If you have not already done so, add authorized users to the file realm of the Application Server as described in Adding Authorized Roles and Users.

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

  4. Browse to the tut-installjavaeetutorial5/examples/web/hello2_basicauth/ directory.

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

  6. Select Open Project.

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

  8. Right-click hello2_basicauth in the Projects pane, then select Undeploy and Deploy.

  9. 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. If you have not already done so, follow the instructions in Building the Examples. This step is necessary to provide the Ant targets with the location of your tutorial and Application Server installations.

  2. If you have not already done so, add authorized users to the file realm of the Application Server as described in Adding Authorized Roles and Users.

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

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


    ant
    

    This command uses web.xml and sun-web.xml files, located in the tut-install/javaeetutorial5/examples/web/hello2_basicauth/web/WEB-INF/ directory.

  5. 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.

  6. 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:

    http://localhost:8080/hello2_basicauth/greeting

    If you set the transport guarantee to CONFIDENTIAL as discussed in Protecting Passwords with SSL, you must load the application in a web browser using https for the protocol, the HTTPS port that you specified during installation for the port (by default this port is 8181), and the context name for the application you wish to run. For the basic authentication example, you could run the example using the following URL: https://localhost:8181/hello2_basicauth/greeting.

  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 Application Server and has been assigned to the group of user, as discussed in Adding Authorized Roles and Users.

    Basic authentication is case-sensitive for both the user name and password, so enter the user name and password exactly as defined for the Application 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 Application 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 Application Server.

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

    • The role of helloUser, as defined for the application, is mapped to the group of user, as defined for the Application Server.

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

  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 30–10.

Figure 30–9 Running the Application

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

Figure 30–10 The Running Basic Authentication Example

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:

    http://localhost:8080/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:

    http://localhost:8080/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.

If the topic of authentication is new to you, refer to the section titled Specifying an Authentication Mechanism. For an explanation of how basic authentication works, see Figure 30–2.

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

This example service was developed by starting with an unsecured service, helloservice, which can be found in the directory tut-install/javaeetutorial5/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. The example client used in this application can be found at tut-install/javaeetutorial5/examples/jaxws/simpleclient-basicauth, which only varies from the original simpleclient application in that it uses the helloservice-basicauth endpoint instead of the helloservice endpoint. The completed version of the secured service can be found at tut-install/javaeetutorial5/examples/jaxws/helloservice-basicauth.

    In general, the following steps are necessary to add basic authentication to a JAX-WS web service. 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.

  1. Create an application like the one in Creating a Simple Web Service and Client with JAX-WS. The example in this tutorial starts with that example and demonstrates adding basic authentication of the client to this application. The completed version of this application is located in the directories tut-install/javaeetutorial5/examples/jaxws/helloservice-basicauth and tut-install/javaeetutorial5/examples/jaxws/simpleclient-basicauth.

  2. If the port value was set to a value other than the default (8080), follow the instructions in Setting the Port to update the example files to reflect this change.

  3. If you have not already done so, follow the steps in Building the Examples for information on setting up your system to run the example.

  4. If you have not already done so, add a user to the file realm and specify user for the group of this new user. Write down the user name and password so that you can use them for testing this application in a later step. If you have not already completed this step, refer to the section Managing Users and Groups on the Application Server for instructions.

  5. Modify the source code for the service, Hello.java, to specify which roles are authorized to access the sayHello (String name) method. This step is discussed in Annotating the Service.

  6. 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.

  7. Modify the runtime deployment descriptor, sun-web.xml, to map the role used in this application (basicUser) to a group defined on the Application Server (user). This step is discussed in Linking Roles to Groups.

  8. 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.

  9. 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.

Annotating the Service

In this example, annotations are used to specify which users are authorized to access which methods of this service. In this simple example, the @RolesAllowed annotation is used to specify that users in the application role of basicUser are authorized access to the sayHello(String name) method. This application role must be linked to a group of users on the Application Server. Linking the roles to groups is discussed in Linking Roles to Groups.

The source code for the original /helloservice application was modified as shown in the following code snippet (modifications in bold). This file can be found in the following location:


tut-install/javaeetutorial5/examples/jaxws/helloservice-basicauth/src/java/helloservice/
basicauth/endpoint/Hello.java

The code snippet is as follows:

package helloservice.basicauth.endpoint;

import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.annotation.security.RolesAllowed;
@WebService()
public class Hello {
     private String message = new String("Hello, ");

    @WebMethod()
    @RolesAllowed("basicUser")
    public String sayHello(String name) {
         return message + name + ".";

    }
}

The @RolesAllowed annotation specifies that only users in the role of basicUser will be allowed to access the sayHello (String name) method. An @RolesAllowed annotation implicitly declares a role that will be referenced in the application, therefore, no @DeclareRoles annotation is required.

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> and <login-config>elements. These security elements are discussed in more detail in Declaring Security Requirements in a Deployment Descriptor and in the Java Servlet Specification. Code in bold is added to the original deployment descriptor to enable HTTP basic authentication. The resulting deployment descriptor is located in tut-install/javaeetutorial5/examples/jaxws/helloservice-basicauth/web/WEB-INF/web.xml.

<?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>basicUser</role-name>
        </auth-constraint>
        <user-data-constraint>
            <transport-guarantee>NONE</transport-guarantee>
        </user-data-constraint>
    </security-constraint>
    <login-config>
        <auth-constraint>BASIC</auth-constraint>
        <realm-name>file</realm-name>
    </login-config>
</web-app>

Linking Roles to Groups

The role of basicUser has been defined for this application, but there is no group of basicUser defined for the Application Server. To map the role that is defined for the application (basicUser) to a group that is defined on the Application Server (user), add a <security-role-mapping> element to the runtime deployment descriptor, sun-web.xml, as shown below (modifications from the original file are in bold). The resulting runtime deployment descriptor is located in tut-install/javaeetutorial5/examples/jaxws/helloservice-basicauth/web/WEB-INF/sun-web.xml.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE sun-web-app PUBLIC 
"-//Sun Microsystems, Inc.//DTD Application Server 9.0 Servlet 2.5//EN" 
"http://www.sun.com/software/appserver/dtds/sun-web-app_2_5-0.dtd">
<sun-web-app error-url="">
    <context-root>/helloservice</context-root>
    <class-loader delegate="true"/>
    <security-role-mapping>
         <role-name>basicUser</role-name>
        <group-name>user</group-name>
    </security-role-mapping>
</sun-web-app>

Building and Deploying helloservice with Basic Authentication Using NetBeans IDE

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

  1. If you have not already done so, set up your system for running the tutorial examples by following the instructions in Building the Examples.

  2. If you haven’t already done so, set up an authorized user on the Application Server, assigned to the group user, as described in Managing Users and Groups on the Application Server.

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

  4. In the Open Project dialog, navigate to tut-install/javaeetutorial5/examples/jaxws/.

  5. Select the helloservice-basicauth folder.

  6. Check the Open as Main Project and Open Required Projects check boxes.

  7. Click Open Project.

  8. In the Projects tab, right-click the helloservice-basicauth project and select Clean and Build.

  9. In the Projects tab, right-click the helloservice-basicauth project and select Undeploy and Deploy.

    This step builds and packages the application into helloservice-basicauth.war, located in tut-install/javaeetutorial5/examples/jaxws/helloservice-basicauth/dist, and deploys this war file to your Application Server instance.

Building and Deploying helloservice with Basic Authentication Using Ant

    To build, package, and deploy the jaxws/helloservice-basicauth example using the Ant tool, follow these steps, or the steps described in Building, Packaging, and Deploying the Service.

  1. If you have not already done so, set up your system for running the tutorial examples by following the instructions in Building the Examples.

  2. If you haven’t already done so, set up an authorized user on the Application Server, assigned to the group user, as described in Managing Users and Groups on the Application Server.

  3. From a terminal window or command prompt, go to the tut-install/javaeetutorial5/examples/jaxws/helloservice-basicauth/ directory.

  4. Build, package, and deploy the JAX-WS service by entering the following at the terminal window or command prompt in the helloservice-basicauth/ directory:


    ant all
    

You can test the service by selecting it in the Admin Console and choosing Test. 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, simpleclient-basicauth, using NetBeans IDE, follow these steps. The helloservice-basicauth service must be deployed onto the Application 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 tut-install/javaeetutorial5/examples/jaxws/.

  3. Select the simpleclient-basicauth folder.

  4. Check the Open as Main Project and Open Required Projects check boxes.

  5. Click Open Project.

  6. In the Projects tab, right-click the simpleclient-basicauth project and select Clean and Build.

  7. In the Projects tab, right-click the simpleclient-basicauth project and select Run.

    You will be prompted for your user name and password.

  8. 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 user.

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

The client displays the following output:


[echo] running application client container.
[exec] Retrieving the port from the following service: 
helloservice.basicauth.endpoint.HelloService@c8769b
[exec] Invoking the sayHello operation on the port.
[exec] Hello, No Name.

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

    To build and run the client application, simpleclient-basicauth, using the Ant tool, follow these steps. The secured service must be deployed onto the Application 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 directory tut-install/examples/jaxws/simpleclient-basicauth/ 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, simpleclient-basicauth.jar, located in the /dist directory.

  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 Application Server with a group of user. Click OK.

The client displays the following output:


[echo] running application client container.
[exec] Retrieving the port from the following service: 
helloservice.basicauth.endpoint.HelloService@c8769b
[exec] Invoking the sayHello operation on the port.
[exec] Hello, No Name.