Author: asanso
Date: Fri Aug 8 05:31:48 2014
New Revision: 1616677
URL: http://svn.apache.org/r1616677
Log:
SLING-3815 - Add support for X-Content-Type-Options: nosniff
Added:
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/StaticResponseHeader.java
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/StaticResponseHeaderTest.java
Modified:
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingHttpServletResponseImpl.java
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java
Modified:
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingHttpServletResponseImpl.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingHttpServletResponseImpl.java?rev=1616677&r1=1616676&r2=1616677&view=diff
==============================================================================
---
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingHttpServletResponseImpl.java
(original)
+++
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingHttpServletResponseImpl.java
Fri Aug 8 05:31:48 2014
@@ -43,6 +43,12 @@ public class SlingHttpServletResponseImp
super(response);
this.requestData = requestData;
this.firstSlingResponse = !(response instanceof
SlingHttpServletResponse);
+
+ if (firstSlingResponse && RequestData.getAdditionalResponseHeaders()
!= null) {
+ for (StaticResponseHeader mapping:
RequestData.getAdditionalResponseHeaders()) {
+ response.addHeader(mapping.getResponseHeaderName(),
mapping.getResponseHeaderValue());
+ }
+ }
}
protected final RequestData getRequestData() {
Modified:
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java?rev=1616677&r1=1616676&r2=1616677&view=diff
==============================================================================
---
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
(original)
+++
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/SlingMainServlet.java
Fri Aug 8 05:31:48 2014
@@ -110,6 +110,14 @@ public class SlingMainServlet extends Ge
@Property
private static final String PROP_SERVER_INFO = "sling.serverinfo";
+
+
+ @Property(value = {"X-Content-Type-Options=nosniff"},
+ label = "Additional response headers",
+ description = "Provides mappings for additional response headers "
+ + "Each entry is of the form 'bundleId [ \":\"
responseHeaderName ] \"=\" responseHeaderValue' ",
+ unbounded = PropertyUnbounded.ARRAY)
+ private static final String PROP_ADDITIONAL_RESPONSE_HEADERS =
"sling.additional.response.headers";
@Reference
private HttpService httpService;
@@ -173,7 +181,7 @@ public class SlingMainServlet extends Ge
private ServiceRegistration requestProcessorMBeanRegistration;
private String configuredServerInfo;
-
+
// ---------- Servlet API -------------------------------------------------
@Override
@@ -334,6 +342,22 @@ public class SlingMainServlet extends Ge
@Activate
protected void activate(final BundleContext bundleContext,
final Map<String, Object> componentConfig) {
+
+ final String[] props =
PropertiesUtil.toStringArray(componentConfig.get(PROP_ADDITIONAL_RESPONSE_HEADERS));
+
+ final ArrayList<StaticResponseHeader> mappings = new
ArrayList<StaticResponseHeader>(props.length);
+ for (final String prop : props) {
+ if (prop != null && prop.trim().length() > 0 ) {
+ try {
+ final StaticResponseHeader mapping = new
StaticResponseHeader(prop.trim());
+ mappings.add(mapping);
+ } catch (final IllegalArgumentException iae) {
+ log.info("configure: Ignoring '{}': {}", prop,
iae.getMessage());
+ }
+ }
+ }
+ RequestData.setAdditionalResponseHeaders(mappings);
+
configuredServerInfo =
PropertiesUtil.toString(componentConfig.get(PROP_SERVER_INFO), null);
// setup server info
Added:
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/StaticResponseHeader.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/StaticResponseHeader.java?rev=1616677&view=auto
==============================================================================
---
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/StaticResponseHeader.java
(added)
+++
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/StaticResponseHeader.java
Fri Aug 8 05:31:48 2014
@@ -0,0 +1,68 @@
+/*
+ * 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.sling.engine.impl;
+
+/**
+ * The <code>Mapping</code> class defines the mapping of a optional additional
+ * response headers
+ */
+public class StaticResponseHeader {
+
+ private final String responseHeaderName;
+
+ private final String responseHeaderValue;
+
+ /**
+ * Creates a mapping entry for the entry specification of the form:
+ *
+ * <pre>
+ * spec = responseHeaderName "=" responseHeaderValue .
+ * </pre>
+ *
+ * @param spec The mapping specification.
+ * @throws NullPointerException if {@code spec} is {@code null}.
+ * @throws IllegalArgumentException if {@code spec} does not match the
+ * expected pattern.
+ */
+ StaticResponseHeader(final String spec) {
+
+ if (spec.length() == 0) {
+ throw new IllegalArgumentException("responseHeader must not be
empty");
+ }
+
+ final int equals = spec.indexOf('=');
+
+ if (equals <= 0) {
+ throw new IllegalArgumentException("responseHeaderName is
required");
+ } else if (equals == spec.length() - 1) {
+ throw new IllegalArgumentException("responseHeaderValue is
required");
+ }
+
+ this.responseHeaderName = spec.substring(0, equals);
+ this.responseHeaderValue = spec.substring(equals + 1);
+ }
+
+ public String getResponseHeaderName() {
+ return responseHeaderName;
+ }
+
+ public String getResponseHeaderValue() {
+ return responseHeaderValue;
+ }
+}
Modified:
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java?rev=1616677&r1=1616676&r2=1616677&view=diff
==============================================================================
---
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java
(original)
+++
sling/trunk/bundles/engine/src/main/java/org/apache/sling/engine/impl/request/RequestData.java
Fri Aug 8 05:31:48 2014
@@ -23,6 +23,7 @@ import static org.apache.sling.api.Sling
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
+import java.util.ArrayList;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
@@ -46,6 +47,7 @@ import org.apache.sling.api.resource.Res
import org.apache.sling.api.servlets.ServletResolver;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.apache.sling.api.wrappers.SlingHttpServletResponseWrapper;
+import org.apache.sling.engine.impl.StaticResponseHeader;
import org.apache.sling.engine.impl.SlingHttpServletRequestImpl;
import org.apache.sling.engine.impl.SlingHttpServletRequestImpl3;
import org.apache.sling.engine.impl.SlingHttpServletResponseImpl;
@@ -108,6 +110,8 @@ public class RequestData {
private static SlingMainServlet SLING_MAIN_SERVLET;
private static SlingHttpServletRequestFactory REQUEST_FACTORY;
+
+ private static ArrayList<StaticResponseHeader> ADDITIONAL_RESPONSE_HEADERS;
/** The SlingMainServlet used for request dispatching and other stuff */
private final SlingRequestProcessorImpl slingRequestProcessor;
@@ -180,6 +184,14 @@ public class RequestData {
RequestData.SLING_MAIN_SERVLET = slingMainServlet;
RequestData.REQUEST_FACTORY = null;
}
+
+ public static void
setAdditionalResponseHeaders(ArrayList<StaticResponseHeader> mappings){
+ RequestData.ADDITIONAL_RESPONSE_HEADERS = mappings;
+ }
+
+ public static ArrayList<StaticResponseHeader>
getAdditionalResponseHeaders() {
+ return ADDITIONAL_RESPONSE_HEADERS;
+ }
public RequestData(SlingRequestProcessorImpl slingRequestProcessor,
HttpServletRequest request, HttpServletResponse response) {
Added:
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/StaticResponseHeaderTest.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/StaticResponseHeaderTest.java?rev=1616677&view=auto
==============================================================================
---
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/StaticResponseHeaderTest.java
(added)
+++
sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/StaticResponseHeaderTest.java
Fri Aug 8 05:31:48 2014
@@ -0,0 +1,88 @@
+/*
+ * 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.sling.engine.impl;
+
+import junit.framework.TestCase;
+import org.junit.Test;
+
+public class StaticResponseHeaderTest {
+
+ @Test
+ public void test_constructor_null() {
+ try {
+ new StaticResponseHeader(null);
+ TestCase.fail("NullPointerException expected");
+ } catch (NullPointerException npe) {
+ // expected
+ }
+ }
+
+ @Test
+ public void test_constructor_empty() {
+ try {
+ new StaticResponseHeader("");
+ TestCase.fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+
+ @Test
+ public void test_constructor_missing_responseHeaderValue() {
+ try {
+ new StaticResponseHeader("responseHeader");
+ TestCase.fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+
+ try {
+ new StaticResponseHeader("responseHeaderName=");
+ TestCase.fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+
+ @Test
+ public void test_constructor_missing_responseHeaderName() {
+ try {
+ new StaticResponseHeader("=user");
+ TestCase.fail("IllegalArgumentException expected");
+ } catch (IllegalArgumentException iae) {
+ // expected
+ }
+ }
+
+ @Test
+ public void test_constructor_and_map() {
+ assertMapping("responseHeaderName", "responseHeaderValue");
+ }
+
+ private void assertMapping(final String responseHeaderName, final String
responseHeaderValue) {
+ StringBuilder spec = new StringBuilder();
+ spec.append(responseHeaderName);
+ spec.append('=').append(responseHeaderValue);
+
+ // spec analysis
+ final StaticResponseHeader mapping = new
StaticResponseHeader(spec.toString());
+ TestCase.assertEquals(responseHeaderName,
mapping.getResponseHeaderName());
+ TestCase.assertEquals(responseHeaderValue,
mapping.getResponseHeaderValue());
+ }
+}