/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.catalina.filters; import java.io.IOException; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletResponse; import org.apache.juli.logging.Log; import org.apache.juli.logging.LogFactory; /** * Implements HTTP Strict Transport Security (HSTS) according to RFC 6797. *

* The filter assumes that: *

*

Filter Configuration

*

Basic configuration to add ' * Strict-Transport-Security: max-age=31536000 ; includeSubDomains * ' to all responses sent over SSL/TLS

 * <web-app ...>
 *    ...
 *    <filter>
 *       <filter-name>HstsFilter</filter-name>
 *       <filter-class>org.apache.catalina.filters.HstsFilter</filter-class>
 *       <init-param>
 *          <param-name>maxAgeSeconds</param-name>
 *          <param-value>31536000</param-value>
 *       </init-param>
 *       <init-param>
 *          <param-name>includeSubDomains</param-name>
 *          <param-value>true</param-value>
 *       </init-param>
 *    </filter>
 *    ...
 *    <filter-mapping>
 *       <filter-name>HstsFilter</filter-name>
 *       <url-pattern>/*</url-pattern>
 *    </filter-mapping>
 *    ...
 * </web-app>
 * 
* @author Jens Borgland * @see RFC 6797 */ public class HstsFilter extends FilterBase { private static final String HEADER_NAME = "Strict-Transport-Security"; private static final String MAX_AGE_DIRECTIVE = "max-age=%s"; private static final String INCLUDE_SUB_DOMAINS_DIRECTIVE = "includeSubDomains"; private static final Log log = LogFactory.getLog(HstsFilter.class); // The default is "0" like recommended in section 11.2 of RFC 6797 private int maxAgeSeconds = 0; private boolean includeSubDomains = false; private String directives; public void setMaxAgeSeconds(int maxAgeSeconds) { this.maxAgeSeconds = maxAgeSeconds; } public void setIncludeSubDomains(boolean includeSubDomains) { this.includeSubDomains = includeSubDomains; } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); // Note that the HSTS header must not be included in HTTP responses // conveyed over non-secure transport if (request.isSecure() && response instanceof HttpServletResponse) { HttpServletResponse res = (HttpServletResponse) response; res.addHeader(HEADER_NAME, this.directives); } } @SuppressWarnings("boxing") @Override public void init(FilterConfig filterConfig) throws ServletException { super.init(filterConfig); if (this.maxAgeSeconds < 0) { throw new ServletException(sm.getString( "hsts.invalidParameterValue", this.maxAgeSeconds, "maxAgeSeconds")); } this.directives = String.format(MAX_AGE_DIRECTIVE, this.maxAgeSeconds); if (this.includeSubDomains) { this.directives += (" ; " + INCLUDE_SUB_DOMAINS_DIRECTIVE); } } @Override protected Log getLogger() { return log; } }