< Day Day Up > |
4.10 Usage PatternsThe declarative and programmatic security features supported by the Java Servlet specification are used in various ways within enterprise environments. Based on the need, common usage patterns can be used. This section discusses a few usage patterns that have emerged out of common use cases within Web application environments. The patterns identified include connecting to other HTTP servers via HTTPS connections, maintaining the state securely, and performing secure pre- and post-servlet processing. 4.10.1 Using HTTPS to Connect to External HTTP ServersURL connections from servlets to external HTTP servers can be established programamtically using the java.net.URL class. The URL to connect to is passed as a String argument to the URL constructor. Most URLs start with the string http://. When URL connections need to be made over SSL, the protocol is HTTPS, and the URL starts with the string https://. By default, a URL starting with https:// would result in an error�a java.net.MalformedURLException would be thrown�unless an HTTPS protocol handler has been installed on the Java system. For servlets to make HTTPS connections, the Web container hosting the servlet should have the JSSE API (see Section 13.4.1 on page 460) installed and available in the Java runtime class path (see Section 7.2.2 on page 207) with the necessary authorizations granted. Additionally, a JSSE provider must be installed and configured for use by the J2EE programs that need to establish SSL connections (see Section Listing 11.1. on page 384 and Section 11.1.3.3 on page 387). After JSSE is available to be used by the Web container, the system property java.protocol.handler.pkgs may be set to an SSL protocol handler class. This can be done either statically or programmatically. A static configuration usually involves editing a property file on the WAS. A programmatic configuration requires making a System.setProperty() method call. The following line of code shows how to set the IBM SSL protocol handler programmatically:
As we saw in Section 4.9 on page 145, Web components cannot expect to be allowed to set system properties; they can expect to be allowed only to read them. Also, note that multiple Web components may coexist within the same JVM. Therefore, setting a protocol handler will affect other Web components and may conflict with the provider that the container will want to use. Therefore, setting a JVM-wide provider is not a good option. By specifying the appropriate java.net.URLStreamHandler as the third parameter, Web components can provide the protocol handler programmatically when they construct the URL object. For example, the MalformedURLException will no longer be thrown, and the appropriate HTTPS protocol handler will be used for the connection when constructing an HTTPS URL object, as in the following line of code:
When the URL object being constructed is intended to connect to the standard SSL port, 443, it is not necessary to specify the port number as part of the URL. However, if the servlet needs to connect to a nonstandard port�for example, 9443�it is necessary to append the port number to the target URL, as shown in the following line of code:
If a URL refers to a resource hosted on a server that has an invalid or untrusted certificate, an attempt to retrieve the java.io.InputStream or the java.io.OutputStream from the associated java.net.URLConnection object will throw a javax.net.ssl.SSLException with the message untrusted server cert chain. The InputStream and OutputStream can be obtained by calling getInputStream() and getOutputStream() on the URLConnection object, respectively. However, if the server has a valid, trusted certificate, no exception will be thrown. The resultant URL object can be used to open the connection and get the InputStream or OutputStream, as shown next:
When a servlet connects to an external HTTP server, it considers the servlet as a client. If the external HTTP server requires its clients to present their certificates to perform client authentication, as discussed in Section 4.5.1.3 on page 120, the Web container hosting the servlet needs to be configured to connect using the appropriate client certificate. Similar considerations apply when a servlet tries to connect to a server whose server certificate was issued by a nonstandard CA. In this case, if the server is considered trusted, the key store used by the Web container to establish SSL connections between the servlet and the external HTTP servers needs to be updated to include the certificate of the external server the servlet is trying to connect to. 4.10.2 Maintaining the State SecurelyAs we observed in Section 4.5.2 on page 123, HTTP is a stateless protocol. The way HTTP operates is that an HTTP client initiates an HTTP transaction by sending a request to an HTTP server: for example, it asks for a Web page. The server responds; after that, the HTTP transaction is automatically closed. That request has no relation to the next request, if any, the client sends. The advantage of this approach is that it allows an HTTP server to serve multiple clients simultaneously, without incurring the overhead generated by keeping several sessions opened with all the clients that initiated a request. The negative implication is that information about the client, including authentication and personalization information, needs to be resubmitted with every request.
Resubmitting this information with every request is considered user unfriendly and may also have negative security implications. A solution to this problem would be for the Web server to store the information gathered from all the clients on some permanent storage. However, this solution is considered too expensive if implemented on the server side, especially if the HTTP server is contacted by a large number of users. The J2EE architecture supports two solutions to maintain session state: HTTP cookies, and HTTP and SSL sessions. The next two subsections examine how these two solutions work and their security implications in a J2EE environment. 4.10.2.1 HTTP CookiesAn HTTP cookie[5] is a piece of information passed between an HTTP client and server during an HTTP transaction. The cookie is stored on the client machine under the form of a text file and can be shared across multiple requests. For example, the server may store a customer number in a cookie and send it to the client. On subsequent requests, the client will include the current value of that cookie as part of the requests. On receiving a request, the HTTP server extracts the value from the cookie and uses it to identify the session and process the request based on that information.
As part of a well-defined HTTP header, a cookie flows over the network in cleartext. Therefore, eavesdroppers can get at its value easily. When carrying sensitive information, a cookie should be set to be valid for a limited time period and be restricted to flow only over SSL connections. Cookies can be further restricted by taking advantage of their Domain and Path attributes.
Servlets can generate secure cookies, store information in them, and retrieve their contents on subsequent client requests by using the javax.servlet.http.Cookie class offered by the Java Servlet API:
4.10.2.2 HTTP and SSL SessionsHTTP cookies have inherent limited storage capabilities. Another disadvantage is that managing cookies must be handled within the application code. In order to abstract the notion of a session and related state, J2EE supports the notion of an HTTP session, represented as a javax.servlet.http.HttpSession object. Servlets can create an HttpSession object associated with an HTTP request. Any information that needs to be associated with the request can be stored in the HttpSession object. For example, in our travel agency scenario, a customer's current selection of itinerary can be stored in an HttpSession object. Subsequent requests are processed without retrieving all the customer information from the back-end system. Instead, such information is retrieved from the associated HttpSession object. In scenarios like this, an HttpSession is associated with an identifier, jsessionid, that is part of the request. The identifier's value is exchanged either via a cookie or through URL rewriting. In addition to these mechanisms, WASs support sessions by using an SSL session ID as the identifier for an HTTP session. Even though using SSL session IDs tightly links a request to its underlying transport security, this option is not always possible. One reason is that, as we observed in Section 4.5.1.3 on page 120, multiple HTTP servers might form the end point of an SSL handshake, and they may not always have access to the SSL session ID information. Another reason is that SSL sessions may be renegotiated periodically between HTTP clients and servers, resulting in a change of the session ID and hence the loss of HTTP session information. If HTTP session identification is to be maintained through cookies, the Deployer must ensure that they are tranported only over SSL, to prevent eavesdropping and tampering. This helps prevent replay attacks[6] when obtaining the session ID can lead to access to the session itself, including the session information and application state.
Because HTTPSession objects may carry reference to sensitive information, it is also wise to choose a short timeout for the underlying HTTP sessions. If these session identifiers can be obtained by an untrusted third party, setting a small timeout will reduce the time window within which attacks may be possible. The timeout can be specified in a Web application's deployment descriptor and is specified in whole minutes. Listing 4.20 shows an example of setting a 30-minute window for an HTTP session. Listing 4.20. Setting an HTTP Session Timeout
4.10.3 Pre- and Post-Servlet ProcessingA common pattern within Web applications is to perform some actions before and/or after processing a servlet. One example is monitoring the number of failed login attempts and taking an action, such as locking the account, after a maximum number of login attempts is reached. However, J2EE does not require facilities for user and account management. One approach to handling pre- and post-servlet processing is through the use of servlet filters. Filters are software components that perform filtering tasks on either the request to a resource�a servlet or static content�or on the response from a resource or both. They allow dynamic�on-the-fly�manipulation of HTTP header and payload information as it flows in and out of Web containers. The Java Servlet API provides the javax.servlet.Filter interface to represent filters. Filters are associated with a servlet or a URI and are invoked on the inbound and outbound call paths. Multiple filters can be associated with a request by chaining the filters. The servlet being filtered becomes the final component in the chain. Each filter in the chain is given an opportunity to handle requests. In J2EE, filter chains are represented as javax.servlet.FilterChain objects. The use of servlet filters is a programming pattern for using a standard API for plugging security services into applications. Examples include login filters to monitor number of login attempts, auditing filters to securely log request details, and encryption filters to encrypt or decrypt the messages that are exchanged with a servlet. Note that even though servlet filters use a standard API, they are considered to be application code. Therefore, they need to be packaged with the Web applications with which they are associated. Alternatively, a given set of filters for an environment may get explicitly associated with all Web applications. Let us consider a simple scenario in which a certain set of users must be prevented from logging in. A servlet filter can be designed to check whether a user attempting to log in is on this revocation list. The skeleton code in Listing 4.21 can be customized to address the requirements as appropriate�for example, to obtain the revocation list from a database, LDAP directory, and so on. Listing 4.21. CheckUserStatus.java
|
< Day Day Up > |
No comments:
Post a Comment