Metawerx Java Hosting Small Logo

Forcing SSL for sections of your website

Author: Neale Rudd, Metawerx

Date: 25-Nov-2006, updated 02-Sep-2017

If the data being displayed or entered on your website is sensitive or private, SSL should be used to ensure that third parties are not able to view the data in transit, and that data remains confidential.

If it is important that data is sent and received in its entirity and without modification, SSL can also be used to ensure the data is integral.

Tomcat, and other JSP containers can guarantee that SSL is used for certain areas of your site. This can be achieved by adding a security constraint to your web.xml file.

You can either protect your entire site, or a small section of it, such as a folder or individual page.

This is very simple, and only requires an SSL certificate, and the text below to be copy/pasted into your web.xml.

Example 1 - Entire site

To force the use of SSL for your entire website / application, insert the following into your web.xml file, between the <web-app> tags.
<!-- Force SSL for entire site -->
<security-constraint>

	<web-resource-collection>
		<web-resource-name>Entire Application</web-resource-name>
		<url-pattern>/*</url-pattern>
	</web-resource-collection>

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

</security-constraint>

Example 2 - Specific folder

To specify a single folder only, modify the <url-pattern>. The following example protects only the /members folder of the site.
<!-- Force SSL for entire site -->
<security-constraint>

	<web-resource-collection>
		<web-resource-name>Members Folder</web-resource-name>
		<url-pattern>/members/*</url-pattern>
	</web-resource-collection>

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

</security-constraint>

Example 3 - Entire site, but ignore some sections

To ignore a specific section of your site, specify that first, with a transport-guarantee of NONE.. The following example protects all pages except the notify.jsp page.
<!-- Don't force SSL on notify.jsp -->
<security-constraint>
	<web-resource-collection>
		<web-resource-name>Notify page, accessed internally by application</web-resource-name>
		<url-pattern>/notify.jsp</url-pattern>
	</web-resource-collection>
	<user-data-constraint>
		<transport-guarantee>NONE</transport-guarantee>
	</user-data-constraint>
</security-constraint>

<!-- Force SSL for entire site -->
<security-constraint>
	<web-resource-collection>
		<web-resource-name>Entire Site</web-resource-name>
		<url-pattern>/*</url-pattern>
	</web-resource-collection>
	<user-data-constraint>
		<transport-guarantee>CONFIDENTIAL</transport-guarantee>
	</user-data-constraint>
</security-constraint>

Advanced - Enforcing a 301 redirect (02-Sep-2017)

By default, using a security-constraint will cause the container to redirect from HTTP to HTTPS using a 302 (Found) status code.

For SEO purposes, a 301 (Moved Permanently) status code may be preferred. Be aware that this will instruct clients that the page has permanently moved and not to bother checking the http version any longer.

Since Tomcat 7.0.70, 8.0.37, 8.5.4, there is a new attribute transportGuaranteeRedirectStatus which can be used to change the status code. This element is added to the Realm in server.xml, since the Realm is responsible for the redirect itself. In most cases, your top-level Realm will be the LockOutRealm. If you have nested Realms, you will need to add it to the relevant Realm declaration. If you don't have an existing Realm declared, the NullRealm is used by default. In this case, you will need to explicitly declare the NullRealm to add the attribute, or use the default LockOutRealm as in the example below.

Here is an example which forces the redirect to use a 301 status. Note this change goes into server.xml, not web.xml.

  <Realm className="org.apache.catalina.realm.LockOutRealm" transportGuaranteeRedirectStatus="301">
    <!-- This Realm uses the UserDatabase configured in the global JNDI
         resources under the key "UserDatabase".  Any edits
         that are performed against this UserDatabase are immediately
         available for use by the Realm.  -->
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm"
           resourceName="UserDatabase" />
  </Realm>

What each element does

  • <security-constraint> - defines a secured area of the application, which may be the entire site/application, or a specific area only.
  • <web-resource-collection> - defines the resource to be protected, giving it a name and URL pattern.
  • <web-resource-name> - a name for the resource, this can be anything you like.
  • <url-pattern> - the specific pattern to match URIs against. /* matches all URIs. See this page for other example patterns.
  • <user-data-constraint> - the element which defines the data protection to use for this protected resource (basically just a parent element for <transport-guarantee>.
  • <transport-guarantee> - the element which specifies the exact level of data protection required (NONE, INTEGRAL or CONFIDENTIAL).

How it works (in Tomcat)

  • When a client request arrives, the container checks the transport-guarantee for the requested URI. For example, if your <url-pattern> is set to /* then all URIs are protected (ie: the entire application).
  • If the data protection level is set to INTEGRAL or CONFIDENTIAL, and the user is not already using SSL, then a redirect is sent to the client, redirecting to the same URI, but using the port defined in the redirectPort attribute in the <Connector> element in server.xml. By default, this is 443, so in other words the user is redirected to the same page using SSL.

Special notes for JBoss (even though it has an embedded Tomcat engine).

  • The redirectPort attribute in the <Connector> element in server.xml in JBoss is ignored due to an entry in the ServiceBindingManager config. For example, if you are trying to redirect to port 443, but are ending up on the JBoss default 8443 redirect port, even though your redirectPort is set to 443, then you are being affected by this problem. See the guide on How to stop redirectPort being ignored in JBoss for more info.

Try it out

This technique is used by the metawerx account payments page. The entire application has been protected using Example 1 above. To try it out, browse to an HTTP based version of the page http://secure.metawerx.net/payments/. You will notice you are redirected to the HTTPS version of the page automatically by Tomcat.

Which version of JSP / Servlets is required?

The <transport-guarantee> element has been available since JSP 1.1 / Servlets 2.2. Therefore, it should work on all versions of Tomcat, as version 3.0 (the first release was Servlet 2.2 / JSP 1.1 compatible).

See Also

navigation
metawerx specific
search
Share
tools
help

referring pages

Share