All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.security.web.header.writers.HstsHeaderWriter Maven / Gradle / Ivy

There is a newer version: 6.2.4
Show newest version
/*
 * Copyright 2002-2013 the original author or authors.
 *
 * Licensed 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.springframework.security.web.header.writers;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.springframework.security.web.header.HeaderWriter;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;

/**
 * Provides support for HTTP Strict Transport
 * Security (HSTS).
 *
 * 

* By default the expiration is one year and subdomains will be included. This can be * customized using {@link #setMaxAgeInSeconds(long)} and * {@link #setIncludeSubDomains(boolean)} respectively. *

* *

* Since section 7.2 states * that HSTS Host MUST NOT include the STS header in HTTP responses, the default behavior * is that the "Strict-Transport-Security" will only be added when * {@link HttpServletRequest#isSecure()} returns {@code true} . At times this may need to * be customized. For example, in some situations where SSL termination is used, something * else may be used to determine if SSL was used. For these circumstances, * {@link #setRequestMatcher(RequestMatcher)} can be invoked with a custom * {@link RequestMatcher}. *

* * @author Rob Winch * @since 3.2 */ public final class HstsHeaderWriter implements HeaderWriter { private static final long DEFAULT_MAX_AGE_SECONDS = 31536000; private static final String HSTS_HEADER_NAME = "Strict-Transport-Security"; private final Log logger = LogFactory.getLog(getClass()); private RequestMatcher requestMatcher; private long maxAgeInSeconds; private boolean includeSubDomains; private String hstsHeaderValue; /** * Creates a new instance * * @param requestMatcher maps to {@link #setRequestMatcher(RequestMatcher)} * @param maxAgeInSeconds maps to {@link #setMaxAgeInSeconds(long)} * @param includeSubDomains maps to {@link #setIncludeSubDomains(boolean)} */ public HstsHeaderWriter(RequestMatcher requestMatcher, long maxAgeInSeconds, boolean includeSubDomains) { this.requestMatcher = requestMatcher; this.maxAgeInSeconds = maxAgeInSeconds; this.includeSubDomains = includeSubDomains; updateHstsHeaderValue(); } /** * Creates a new instance * * @param maxAgeInSeconds maps to {@link #setMaxAgeInSeconds(long)} * @param includeSubDomains maps to {@link #setIncludeSubDomains(boolean)} */ public HstsHeaderWriter(long maxAgeInSeconds, boolean includeSubDomains) { this(new SecureRequestMatcher(), maxAgeInSeconds, includeSubDomains); } /** * Creates a new instance * * @param maxAgeInSeconds maps to {@link #setMaxAgeInSeconds(long)} */ public HstsHeaderWriter(long maxAgeInSeconds) { this(new SecureRequestMatcher(), maxAgeInSeconds, true); } /** * Creates a new instance * * @param includeSubDomains maps to {@link #setIncludeSubDomains(boolean)} */ public HstsHeaderWriter(boolean includeSubDomains) { this(new SecureRequestMatcher(), DEFAULT_MAX_AGE_SECONDS, includeSubDomains); } /** * Creates a new instance */ public HstsHeaderWriter() { this(DEFAULT_MAX_AGE_SECONDS); } /* * (non-Javadoc) * * @see org.springframework.security.web.headers.HeaderWriter#writeHeaders(javax * .servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) */ public void writeHeaders(HttpServletRequest request, HttpServletResponse response) { if (this.requestMatcher.matches(request)) { response.setHeader(HSTS_HEADER_NAME, this.hstsHeaderValue); } else if (this.logger.isDebugEnabled()) { this.logger .debug("Not injecting HSTS header since it did not match the requestMatcher " + this.requestMatcher); } } /** * Sets the {@link RequestMatcher} used to determine if the * "Strict-Transport-Security" should be added. If true the header is added, else the * header is not added. By default the header is added when * {@link HttpServletRequest#isSecure()} returns true. * * @param requestMatcher the {@link RequestMatcher} to use. * @throws IllegalArgumentException if {@link RequestMatcher} is null */ public void setRequestMatcher(RequestMatcher requestMatcher) { Assert.notNull(requestMatcher, "requestMatcher cannot be null"); this.requestMatcher = requestMatcher; } /** *

* Sets the value (in seconds) for the max-age directive of the * Strict-Transport-Security header. The default is one year. *

* *

* This instructs browsers how long to remember to keep this domain as a known HSTS * Host. See Section * 6.1.1 for additional details. *

* * @param maxAgeInSeconds the maximum amount of time (in seconds) to consider this * domain as a known HSTS Host. * @throws IllegalArgumentException if maxAgeInSeconds is negative */ public void setMaxAgeInSeconds(long maxAgeInSeconds) { if (maxAgeInSeconds < 0) { throw new IllegalArgumentException( "maxAgeInSeconds must be non-negative. Got " + maxAgeInSeconds); } this.maxAgeInSeconds = maxAgeInSeconds; updateHstsHeaderValue(); } /** *

* If true, subdomains should be considered HSTS Hosts too. The default is true. *

* *

* See Section 6.1.2 * for additional details. *

* * @param includeSubDomains true to include subdomains, else false */ public void setIncludeSubDomains(boolean includeSubDomains) { this.includeSubDomains = includeSubDomains; updateHstsHeaderValue(); } private void updateHstsHeaderValue() { String headerValue = "max-age=" + this.maxAgeInSeconds; if (this.includeSubDomains) { headerValue += " ; includeSubDomains"; } this.hstsHeaderValue = headerValue; } private static final class SecureRequestMatcher implements RequestMatcher { public boolean matches(HttpServletRequest request) { return request.isSecure(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy