Thursday Dec 11, 2008

Changes to Servlet and Filter Registration APIs in Servlet 3.0

Changes to Servlet and Filter Registration APIs in Servlet 3.0

Changes to Servlet and Filter Registration APIs in Servlet 3.0

Right after the Public Review draft of the Servlet 3.0 specification had been handed off to the JCP for publication, the Servlet EG changed the signature of the addServlet and addFilter APIs on javax.servlet.ServletContext. These APIs are new in Servlet 3.0, and allow servlets and filters to be registered at runtime, without having to be declared in a web.xml deployment descriptor.

It was felt that the previous method signatures:

  addServlet(String servletName, String description, String className, Map initParameters, int loadOnStartup, boolean isAsyncSupported)

and

  addFilter(String filterName, String description, String className, Map initParameters, boolean isAsyncSupported)

had too many parameters, and there was concern that these methods would have to be overloaded every time a new parameter was added in the future.

Therefore, the Servlet EG decided to change addServlet to take just servletName and className parameters, and to change addFilter to take just filterName and className parameters, and to have these methods return ServletRegistration and FilterRegistration objects, respectively, on which any further configuration would occur.

For example, the following ServletContextListener registers one servlet and one filter when invoked at its contextInitialized method, and then further configures the registered servlet and filter through their respective ServletRegistration and FilterRegistration objects:

  public void contextInitialized(ServletContextEvent sce) {
      ServletContext sc = sce.getServletContext();

      /\*
       \* Register servlet
       \*/
      ServletRegistration sr = sc.addServlet("NewServlet", "test.NewServlet");
      sr.setInitParameter("servletInitName", "servletInitValue");
      sc.addServletMapping("NewServlet", new String[] {"/newServlet"});

      /\*
       \* Register filter that is going to intercept any requests to the
       \* servlet
       \*/
      FilterRegistration fr = sc.addFilter("NewFilter", "test.NewFilter");
      fr.setInitParameter("filterInitName", "filterInitValue");
      sc.addFilterMappingForServletNames("NewFilter",
          EnumSet.of(DispatcherType.REQUEST), true, "NewServlet");
  }

While these changes are not reflected in the Public Review draft of the Servlet 3.0 specification, they have already been implemented in the trunk version of GlassFish v3, which is going to be the reference implementation of the Servlet 3.0 specification.

Please send any questions or comments to the GlassFish webtier alias, or post them to the GlassFish webtier forum.

Monday Dec 08, 2008

How to downshift from HTTPS to HTTP in your web application

How to downshift from HTTPS to HTTP in your web application

How to downshift from HTTPS to HTTP in your web application

Problem description

Web applications will normally protect any of their web resources that process security-sensitive information (e.g., the login page used by FORM authentication) with SSL, to ensure that the information submitted by the user (e.g., username and password security credentials) will not be transmitted in the clear.

Some web applications will only protect web resources that process security-sensitive information in this manner, while allowing requests for other resources to travel in the clear.

Imagine a user accessing some of the unprotected resources of a web application (over HTTP) before accessing a resource that requires FORM authentication, where the FORM login page is guarded by a transport guarantee of CONFIDENTIAL according to the web application's deployment descriptor. In this case, the protocol will change from HTTP to HTTPS (to satisfy the transport guarantee of the login page), and will remain HTTPS even after the user has authenticated successfully and continues accessing any of the unprotected resources.

The fact that the protocol remains HTTPS once it has been changed to HTTPS, even though HTTPS may no longer be required, can be a problem for performance sensitive applications that do not want to incur the overhead of SSL unless required.

This blog explains how a web application can be written so that the protocol changes back to HTTP when HTTPS is no longer needed.

Solution

Imagine a very simple web application containing two servlets UseHttp.java and UseHttps.java, which are mapped to /useHttp and /useHttps, respectively. Further assume that the web application must satisfy the following requirements:

  • REQ_1: Access to "/useHttps" must be over HTTPS (otherwise, the servlet will throw an exception). This means that if the current protocol is HTTP, it must be upgraded to HTTPS.
  • REQ_2: Access to "/useHttp" must be over HTTP (otherwise, the servlet will throw an exception). This means that if the current protocol is HTTPS, it must be downshifted to HTTP.

REQ_1 will be handled automatically by the container, by declaring the following security constraint in the web application's web.xml:

  <security-constraint>
    <web-resource-collection>
      <web-resource-name>Protected resource</web-resource-name>
       <url-pattern>/useHttps</url-pattern>
       <http-method>GET</http-method>
    </web-resource-collection>
    <user-data-constraint>
      <transport-guarantee>CONFIDENTIAL</transport-guarantee>
    </user-data-constraint>
  </security-constraint>

REQ_2 cannot be handled automatically by the container, and must be implemented by the application itself. In order to address REQ_2, we are going to implement a filter that intercepts every request and determines programmtically whether the target resource is guarded by a transport guarantee of CONFIDENTIAL. If it is not, and the request came in over HTTPS, the filter will issue a redirect to the target resource over HTTP.

In order to determine if a requested resource is guarded by HTTPS, the filter leverages the JavaTM Authorization Contract for Containers (Java ACC), which defines new java.security.Permission classes to satisfy the authorization model of the Java Platform, Enterprise Edition. In our particular case, the filter creates and uses an instance of javax.security.jacc.WebUserDataPermission to check if the target resource of a request is guarded by HTTPS.

The complete source code of the filter and the two servlets, as well as the web.xml, are provided as part of the sample application's WAR file and may be downloaded from this link.

For the sake of simplicity, we assume the default GlassFish configuration of three HTTP listeners: one listener reserved for any admin requests, a second listener for user traffic over HTTP (on port 8080), and a third listener for user traffic over HTTPS (on port 8181). (Notice that when you are using GlassFish v3 Prelude, you must enable the HTTPS listener on port 8181, which is disabled by default.)

The port number of the HTTP port for user requests is fed into the filter via an init parameter in web.xml:

  <filter>
    <filter-name>MyFilter</filter-name>
    <filter-class>MyFilter</filter-class>
    <init-param>
      <param-name>httpPort</param-name>
      <param-value>8080</param-value>
    </init-param>
  </filter>

This is necessary so that the filter will know which port number to use when redirecting from HTTPS to HTTP.

Demo

To see the upshift from HTTP to HTTPS, and downshift from HTTPS to HTTP in action, follow these simple steps:

  1. Download and install GlassFish v2 UR2 or GlassFish v3 Prelude.
  2. Download the sample web application sample.war, and deploy it to GlassFish.
  3. Access this URL: http://leah:8080/sample/useHttps. Notice how the request gets redirected to the HTTPS port, and how the protocol changes from HTTP to HTTPS: https://localhost:8181/sample/useHttps.
  4. Now edit the above HTTPS URL in your browser's address window by removing the trailing s from useHttps, so that the URL reads: https://localhost:8181/sample/useHttp, and hit return. Notice how the browser displays this warning message: You are about to leave an encrypted page. Information you send or receive from now on could easily be read by a third party, before issuing a redirect to the HTTP port and downshifting the protocol from HTTPS to HTTP: http://localhost:8080/sample/useHttp

I hope you found this blog useful. Please send any questions or comments you may have to the GlassFish webtier alias, or post them to the GlassFish webtier forum. I also would like to thank GlassFish security architect Ron Monzillo for his Java ACC related contribution to the idea behind this blog and to the filter code of the sample web application.

About

jluehe

Search

Categories
Archives
« December 2008 »
SunMonTueWedThuFriSat
 
1
2
3
4
5
6
7
9
10
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
   
       
Today