[java-support] branch master updated: IDP-627 - Support HSTS, CSP, X-Frame-Options, etc.
Scott Cantor
cantor.2 at osu.edu
Fri Dec 9 20:54:54 EST 2016
This is an automated email from the git hooks/post-receive script.
scantor pushed a commit to branch master
in repository java-support.
View the commit online:
http://git.shibboleth.net/view/?p=java-support.git;a=commit;h=a54d171d42ba714fb7557d46fdf4ad7acaaca915
The following commit(s) were added to refs/heads/master by this push:
new a54d171 IDP-627 - Support HSTS, CSP, X-Frame-Options, etc.
a54d171 is described below
commit a54d171d42ba714fb7557d46fdf4ad7acaaca915
Author: Scott Cantor <cantor.2 at osu.edu>
AuthorDate: Fri Dec 9 20:54:51 2016 -0500
IDP-627 - Support HSTS, CSP, X-Frame-Options, etc.
https://issues.shibboleth.net/jira/browse/IDP-627
Implement a filter to control response headers.
---
pom.xml | 4 +-
.../support/net/DynamicResponseHeaderFilter.java | 201 +++++++++++++++++++++
2 files changed, 203 insertions(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index 0326e7a..125e3f2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -7,13 +7,13 @@
<parent>
<groupId>net.shibboleth</groupId>
<artifactId>parent-v3</artifactId>
- <version>10</version>
+ <version>TRUNK-SNAPSHOT</version>
</parent>
<name>java-support</name>
<groupId>net.shibboleth.utilities</groupId>
<artifactId>java-support</artifactId>
- <version>7.3.1-SNAPSHOT</version>
+ <version>7.4.0-SNAPSHOT</version>
<packaging>jar</packaging>
<repositories>
diff --git a/src/main/java/net/shibboleth/utilities/java/support/net/DynamicResponseHeaderFilter.java b/src/main/java/net/shibboleth/utilities/java/support/net/DynamicResponseHeaderFilter.java
new file mode 100644
index 0000000..7f4dfa7
--- /dev/null
+++ b/src/main/java/net/shibboleth/utilities/java/support/net/DynamicResponseHeaderFilter.java
@@ -0,0 +1,201 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID 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 net.shibboleth.utilities.java.support.net;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Collections2;
+
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullElements;
+import net.shibboleth.utilities.java.support.collection.Pair;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * Implementation of an HTTP servlet {@link Filter} which supports configurable response header
+ * injection, including via injected functions that can conditionally attach headers.
+ */
+public class DynamicResponseHeaderFilter implements Filter {
+
+ /** Statically defined headers to return. */
+ @Nonnull @NonnullElements private Map<String,String> headers;
+
+ /** Callbacks to add headers dynamically. */
+ @Nonnull @NonnullElements
+ private Collection<Function<Pair<HttpServletRequest,HttpServletResponse>,Boolean>> callbacks;
+
+ /** Constructor. */
+ public DynamicResponseHeaderFilter() {
+ headers = Collections.emptyMap();
+ callbacks = Collections.emptyList();
+ }
+
+ /**
+ * Set the headers to statically attach to all responses.
+ *
+ * @param map header map
+ */
+ public void setHeaders(@Nullable @NonnullElements final Map<String,String> map) {
+ if (map != null) {
+ headers = new HashMap<>(map.size());
+ for (final Map.Entry<String,String> entry : map.entrySet()) {
+ final String trimmed = StringSupport.trimOrNull(entry.getKey());
+ if (trimmed != null && entry.getValue() != null) {
+ headers.put(trimmed, entry.getValue());
+ }
+ }
+ } else {
+ headers = Collections.emptyMap();
+ }
+ }
+
+ /**
+ * Set the callbacks to invoke to dynamically attach headers.
+ *
+ * @param theCallbacks callback collection
+ */
+ public void setCallbacks(@Nullable @NonnullElements
+ final Collection<Function<Pair<HttpServletRequest,HttpServletResponse>,Boolean>> theCallbacks) {
+ if (theCallbacks != null) {
+ callbacks = new ArrayList<>(Collections2.filter(theCallbacks, Predicates.notNull()));
+ } else {
+ callbacks = Collections.emptyList();
+ }
+ }
+
+ /** {@inheritDoc} */
+ public void init(final FilterConfig filterConfig) throws ServletException {
+ }
+
+ /** {@inheritDoc} */
+ public void destroy() {
+ }
+
+ /** {@inheritDoc} */
+ public void doFilter(final ServletRequest request, final ServletResponse response, final FilterChain chain)
+ throws IOException,
+ ServletException {
+
+ if (headers.isEmpty() && callbacks.isEmpty()) {
+ chain.doFilter(request, response);
+ return;
+ }
+
+ if (!(request instanceof HttpServletRequest)) {
+ throw new ServletException("Request is not an instance of HttpServletRequest");
+ }
+
+ if (!(response instanceof HttpServletResponse)) {
+ throw new ServletException("Response is not an instance of HttpServletResponse");
+ }
+
+ chain.doFilter(request, new ResponseProxy((HttpServletRequest) request, (HttpServletResponse) response));
+ }
+
+ /**
+ * An implementation of {@link HttpServletResponse} which adds the response headers supplied by the outer class.
+ */
+ private class ResponseProxy extends HttpServletResponseWrapper {
+
+ /** Request. */
+ @Nonnull private final HttpServletRequest request;
+
+ /**
+ * Constructor.
+ *
+ * @param req the request
+ * @param response the response to delegate to
+ */
+ public ResponseProxy(@Nonnull final HttpServletRequest req, @Nonnull final HttpServletResponse response) {
+ super(response);
+
+ request = req;
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public ServletOutputStream getOutputStream() throws IOException {
+ addHeaders();
+ return super.getOutputStream();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public PrintWriter getWriter() throws IOException {
+ addHeaders();
+ return super.getWriter();
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void sendError(final int sc, final String msg) throws IOException {
+ addHeaders();
+ super.sendError(sc, msg);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void sendError(final int sc) throws IOException {
+ addHeaders();
+ super.sendError(sc);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public void sendRedirect(final String location) throws IOException {
+ addHeaders();
+ super.sendRedirect(location);
+ }
+
+ /** Add headers to response. */
+ private void addHeaders() {
+ for (final Map.Entry<String, String> header : headers.entrySet()) {
+ ((HttpServletResponse) getResponse()).addHeader(header.getKey(), header.getValue());
+ }
+
+ if (!callbacks.isEmpty()) {
+ final Pair<HttpServletRequest,HttpServletResponse> p =
+ new Pair<>(request, (HttpServletResponse) getResponse());
+ for (final Function<Pair<HttpServletRequest,HttpServletResponse>,Boolean> callback : callbacks) {
+ callback.apply(p);
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list