Web Container Security Features

The Web container plays an important role in building and deploying secure Web applications. The servlet specification outlines what security features should be part of the environment provided by the Web container and how a specific Web application should make use of them. However, as we soon find out, not all aspects are fully standardized. We will rely on the Tomcat-specific conventions to realize these non-standard features. Such non-standard conventions are clearly marked in the text.

As we go through the security features, we modify our sample application RMB to incorporate some of these features. A modified version of the sample application, with a complete set of security features, is available as RMB2, and is part of the bundled software and can be used for experimentation.

While designing security capabilities and APIs for Web applications, J2EE architects took the view that the Web applications will be created by the developers and will be given, sold, or otherwise transferred to the deployers for deployment into a runtime environment. As the security needs are usually deployment-specific and are largely orthogonal to application functionality (X is said to be orthogonal to Y if one can be changed without impacting another), it should be possible for a deployer to specify such characteristics as per the need of the particular deployment, without the need to change the application code. Examples of such deployment specific security decisions include:

  • Use of an existing user account management system

  • Selection of an authentication scheme

  • Need to use SSL

  • Selection of URLs available to authenticated users only

This is accomplished by declarative specification of security characteristics as part of the deployment time configuration. Of course, not all security needs can be met by declarative means. There are situations when a program must decide whether to perform certain operations on a specific data based on the identity of the current user and application-dependent authorization rules. Such cases are best handled through programmatic security.

Declarative Security

In declarative security, a deployer specifies security characteristics, such as authentication mechanism, authorization to access certain URIs, user roles, and so on, declaratively in the Web application deployment descriptor. As we know, a deployment descriptor is an XML file named web.xml and stored in the WEB-INF directory of the Web application directory structure. This file has web-app as the top-level element and this element has the following structure:

<web-app>
  ... non-security elements ...
  (<resource-ref>)*
  (<security-constraint>)*
  (<login-config>)?
  (<security-role>)*
  (<env-entry>)*
  ... non-security elements ...
</web-app>

Note that all the security-related elements are optional. When one or more of these elements are present, their relative order, among themselves and in relation to other non-security elements, must be maintained as shown above. This order is specified by the deployment descriptor DTD (Document Type Definition) in the servlet specification, and may be validated by the Web container. Tomcat 4.x does this validation.

The element security-constraint is used to restrict the access of a collection of URIs within the Web application to users with a specific role. Additionally, one may also specify characteristics of the transport used to access these URIs. Let us take a look at the structure of the security-constraint element.

<security-constraint>
  (<display-name>descriptive name</display-name>)?
  (<web-resource-collection>
    <web-resource-name>descriptive name</web-resource-name>
    (<description>descriptive text</description>)?
    (<url-pattern>url pattern</url-pattern>)*
    (<http-method>http method</http-method>)*
  </web-resource-collection>)+
  (<auth-constraint>
    (<description>descriptive text</description>)?
    (<role-name>user role</role-name>)*
  </auth-constraint>)?
  (<user-data-constraint>
    (<description>descriptive text</description>)?
    (<transport-guarantee>transport guarantee</transport-guarantee >)
  </user-data-constraint>)?
</security-constraint>

As you can see, a number of these elements have a descriptive name or text associated with them: display-name with security-constraint, web-resource-name with web-resource-collection, and description with web-resource-collection, auth-constraint and user-data-constraint. As far as the Web container is concerned, these are simply opaque strings. Their main purpose is to improve maintenance of the deployment descriptor through visual tools. Other elements require further elaboration:

url-pattern: A url pattern can be (a) a string starting with "/" and ending with "/*" implying path matching; (b) a string starting with "*." implying extension matching; (c) a string "/" implying default servlet; or (d) any string for exact matching. The pattern matching is done for the part of the request URI occurring after the context path of the Web application. For example, if the Web container running on localhost is listening for requests on port 8080, and the context path of the Web application is /rmb, then for the request URI of http://localhost:8080/rmb/ask_post.jsp, the pattern matching will be done for /ask_post.jsp. Examples of valid URL patterns include: /images/*, *.gif, /images/logo.gif. What URI space is covered by each of these patterns? Note that it is possible for one request URI to match multiple patterns. What happens if a URL matches multiple patterns, each within its own security-constraint element? That would be the case for the example patterns and a URL relative to the context path as /images/logo.gif. The servlet specification is not very clear on handling such corner cases. Apache Tomcat processes the first matching security-constraint element in the deployment descriptor file web.xml.

http-method: A specific HTTP method for which access permission is being granted. Valid values are HTTP methods specified by HTTP/1.1 specification: OPTIONS, GET, POST, HEAD, PUT, DELETE, TRACE, CONNECT. If no methods are specified then the constraint applies to all the methods. This might give the impression that by default, PUT and DELETE methods are also available on any URI covered by a security-constraint. This is not the case with Apache Tomcat, at least for URIs served by the default servlets.

role-name: A string identifying a user role. This must match, in a case-sensitive manner, to a role-name element within a security-role element of the same Web application. An exception is a special value consisting of the character '*' that matches any role. If no role-name is specified, no user gets access to the Web resources of the web-resource-collection element. Here the assumption is that a user will be assigned one or more roles and a role name will uniquely identify the role. The mapping of usernames to role name is left to the Web container. With Apache Tomcat, we have already come across the tomcat-users.xml file that has such mapping.

transport-guarantee: It can take one of the following three values: NONE (implying no guarantee of message integrity or confidentiality), INTEGRAL (implying message integrity guarantee) and CONFIDENTIAL (implying message confidentiality guarantee). In practice, INTEGRAL or CONFIDENTIAL implies SSL, and hence, both message integrity and confidentiality. The absence of the user-data-constraint element defaults to transport-guarantee value as NONE. However, just specifying the transport-guarantee as INTEGRAL or CONFIDENTIAL is not sufficient to turn-on SSL. With Apache Tomcat, you must modify the server.xml configuration file so that entry for the Connector entry supporting SSL connections is uncommented and the appropriate keystore file is specified. We talk more about this later. Only when this connector is enabled, an INTEGRAL or CONFIDENTIAL value for transport-guarantee element would redirect the requests with protected URIs to the corresponding HTTPS URIs.

Let us write a security-constraint element for our sample Web application RMB so that only users with rmb2user role can access the JSP pages, and only over SSL:

<security-constraint>
  <display-name>RMB2 Security Constraint</display-name>
  <web-resource-collection>
    <web-resource-name>RMB2 protected files</web-resource-name>
    <url-pattern>*.jsp</url-pattern>
  </web-resource-collection>
  <auth-constraint>
    <role-name>rmb2user</role-name>
  </auth-constraint>
  <user-data-constraint>
    <transport-guarantee>INTEGRAL</transport-guarantee >
  </user-data-constraint>
</security-constraint>

You can find this in the web.xml file of RMB2 Web application.

Different user roles of a Web application are listed as security-role elements. This element has the following structure:

<security-role>
  (<description>descriptive text</description>)?
  <role-name>user role</role-name>
</security-role>

Recall that a role used in an auth-constraint element of security-constraint must be present within a security-role element of the same deployment descriptor. So, we must add the following lines to the deployment descriptor of our sample Web application RMB2:

<security-role>
  <description>Role to Access RMB</description>
  <role-name>rmb2user</role-name>
</security-role>

As noted earlier, mapping of a particular user to a role is done in a Web container implementation-specific manner.

But how does the container get to know the user identity? By requiring the user to supply a user name and login to the container. As we have already seen, there are many ways to perform this authentication: HTTP Basic Authentication, HTTP Digest Authentication, FORM-based Authentication and Client Certificate Authentication.

The element login-config of deployment descriptor indicates the authentication mechanism required by the Web application. This element has the following structure:

<login-config>
  (<auth-method>authentication mechanism</auth-method>)?
  (<realm-name>realm id. String</realm-name>)?
  (<form-login-config>
    <form-login-page>login-page-url</form-login-page>
    <form-error-page>error-page-url</form-error-page>
  </form-login-config>)?
</login-config>

The element auth-method can take following values:

  • BASIC for HTTP Basic Authentication;

  • DIGEST for HTTP Digest Authentication;

  • FORM for FORM-based Authentication; and

  • CLIENT-CERT for Client Certificate Authentication.

For BASIC, DIGEST and FORM authentications, it is the responsibility of the Web container to validate the username and the password. This requires configuring the Web container to interface with a user account system. This interface is not specified by servlet API and usually depends on the Web container implementation. Configuration for CLIENT-CERT authentication is also Web container dependent. We cover this configuration for Apache Tomcat shortly.

The element form-login-config is required only for FORM authentication. The sub-elements specify the page to be shown in the browser to collect username and password, and also the error page in case the login fails. With BASIC and DIGEST authentication, the browser generates a login panel. Recall the login panel generated by the browser for BASIC authentication that we saw while exploring Tomcat Manager. With CLIENT-CERT authentication, the browser either selects a client certificate from its certificate store or asks the user to select a certificate.

BASIC and DIGEST authentications are quite straightforward and do not require any further discussion.

In FORM-based Authentication, the user is presented with a separate login page or login area within an application page whenever a protected page is accessed for the first time. The value of the element form-login-page must be the URL of this page. The Web container also needs the URL of an error page, to be displayed if the login fails. This URL is specified through the form-error-page element.

Shown below is a sample login-config element from the deployment descriptor of RMB2, the secure version of our sample Web application:

// From rmb2WEB-INFweb.xml file
<login-config>
  <auth-method>FORM</auth-method>
  <realm-name>RMB2 Form Based Authentication</realm-name>
  <form-login-config>
    <form-login-page>/login.jsp</form-login-page>
    <form-error-page>/error.jsp</form-error-page>
  </form-login-config>
</login-config>

Let us look at the login.jsp file, stored in the root directory of the Web application, rmb2.

// rmb2/login.jsp file
<%@ page contentType="text/html" %>

<html><body>
<form method="POST" action="j_security_check" name="loginForm">
  <table>
    <tr>
      <td>Username: </td>
      <td><input type="text" name="j_username" size="16"/></td>
    </tr>
    <tr>
      <td>Password: </td>
      <td><input type="password" name="j_password" size="16"/></td>
    </tr>
    <tr>
      <td><input type="submit" value='Login'></td>
      <td><input type="reset" value='Reset'></td>
    </tr>
 </table>
</form></body></html>

The page generated essentially asks the user to enter the username and password.

Pay attention to the value of the action attribute of the element form and the name attribute of the element input. These values, j_security_check, j_username and j_password are specified by the servlet API and are processed by the Web container. This is how the Web container is able to grab the username and password values and do the necessary validation. If the validation fails, it responds with the page generated by error.jsp:

// rmb2/error.jsp
<%@ page contentType="text/html" %>

<html><body>
<h2>Invalid Username or Password
<br/>
To try again, click <a href="">here</a>
</h2>
</body></html>

This page simply informs the user that the login was unsuccessful and presents an option to retry.

Programmatic Security

In cases where declarative security is not adequate for all access control decisions, a program can use program logic to make access control decision based on user identity. The following methods of HttpServletRequest interface provide information about the current user:

getRemoteUser(): returns the username used for authentication as a String object, null if there is no currently logged in user.

isUserInRole(String role): returns true if the current user is associated with the supplied role, false otherwise. Recall that a user may be associated with multiple roles.

getUserPrincipal(): returns the current user as a java.security.Principal object. The concrete object implementing Principal interface depends on the Web container setup for authentication. If you use the default user account system in Apache Tomcat-4.1.18 for BASIC, DIGEST or FORM authentication, the concrete class would be org.apache.catalina.realm.GenericPrincipal. For CLIENT-CERT authentication, the Concrete Principal would be javax.security.auth.x500.X500Principal.

The following JSP fragment can be used to print the current username and the value returned by the toString() method of the Principal object:

RemoteUser: <%= request.getRemoteUser() %>
Principal : <%= request.getUserPrincipal().getName() %>

A working JSP file incorporating this code, show_user.jsp, is available in the root directory of the RMB2 Web application.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.116.126