You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by pa...@apache.org on 2020/01/17 21:27:02 UTC
[wicket] 07/08: WICKET-6727: Remove old CspNonceHeaderResponse and
update example
This is an automated email from the ASF dual-hosted git repository.
papegaaij pushed a commit to branch csp-configurable
in repository https://gitbox.apache.org/repos/asf/wicket.git
commit cfc46152d08d89d259e6666d3f0895e7b63266a0
Author: Emond Papegaaij <em...@topicus.nl>
AuthorDate: Fri Jan 17 22:14:48 2020 +0100
WICKET-6727: Remove old CspNonceHeaderResponse and update example
---
.../markup/head/filter/CspNonceHeaderResponse.java | 93 ----------------------
.../markup/head/filter/CspNoncePageExpected.html | 3 +-
.../head/filter/FilteringHeaderResponseTest.java | 28 ++++++-
.../apache/wicket/examples/csp/CspApplication.java | 35 +-------
4 files changed, 27 insertions(+), 132 deletions(-)
diff --git a/wicket-core/src/main/java/org/apache/wicket/markup/head/filter/CspNonceHeaderResponse.java b/wicket-core/src/main/java/org/apache/wicket/markup/head/filter/CspNonceHeaderResponse.java
deleted file mode 100644
index f2a9ce1..0000000
--- a/wicket-core/src/main/java/org/apache/wicket/markup/head/filter/CspNonceHeaderResponse.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * 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.wicket.markup.head.filter;
-
-import org.apache.wicket.Application;
-import org.apache.wicket.markup.head.AbstractCspHeaderItem;
-import org.apache.wicket.markup.head.HeaderItem;
-import org.apache.wicket.markup.head.IHeaderResponse;
-import org.apache.wicket.markup.head.IWrappedHeaderItem;
-import org.apache.wicket.markup.head.MetaDataHeaderItem;
-import org.apache.wicket.markup.head.ResourceAggregator;
-import org.apache.wicket.markup.html.DecoratingHeaderResponse;
-
-/**
- * Add a <em>Content Security Policy<em> (CSP) nonce to all {@link AbstractCspHeaderItem}s.
- * <p>
- * Note: please don't forget to wrap with {@link ResourceAggregator} when setting it up with
- * {@link Application#setHeaderResponseDecorator}, otherwise dependencies will not be rendered.
- *
- * @see AbstractCspHeaderItem
- */
-public class CspNonceHeaderResponse extends DecoratingHeaderResponse
-{
- private static final String CONTENT_SECURITY_POLICY = "Content-Security-Policy";
-
- /**
- * Has the <em>Content-Security-Policy</em> header been rendered once.
- */
- private boolean policyRendered = false;
-
- private String nonce;
-
- public CspNonceHeaderResponse(IHeaderResponse real, String nonce)
- {
- super(real);
-
- this.nonce = nonce;
- }
-
- @Override
- public void render(HeaderItem item)
- {
- while (item instanceof IWrappedHeaderItem)
- {
- item = ((IWrappedHeaderItem)item).getWrapped();
- }
-
- if (item instanceof AbstractCspHeaderItem)
- {
- if (policyRendered == false)
- {
- policyRendered = true;
-
- String policy = getContentSecurityPolicy(nonce);
-
- super.render(MetaDataHeaderItem.forHttpEquiv(CONTENT_SECURITY_POLICY, policy));
- }
-
- ((AbstractCspHeaderItem)item).setNonce(nonce);
- }
-
- super.render(item);
- }
-
- /**
- * Get the <em>Content-Security-Policy</em> (CSP).
- * <p>
- * There is a variety of CSP configurations, this default implementation uses the nonce for scripts and styles
- * and allows <code>strict-dynamic</code>s (needed for Wicket Ajax).
- *
- * @param nonce
- * the nonce
- * @return content security policy
- */
- protected String getContentSecurityPolicy(String nonce)
- {
- return String.format("script-src 'strict-dynamic' 'nonce-%1$s'; style-src 'nonce-%1$s';", nonce);
- }
-}
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/CspNoncePageExpected.html b/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/CspNoncePageExpected.html
index 2c44fc9..6cf3902 100644
--- a/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/CspNoncePageExpected.html
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/CspNoncePageExpected.html
@@ -1,6 +1,5 @@
<html xmlns:wicket="http://wicket.apache.org/dtds.data/wicket-xhtml1.4-strict.dtd" >
- <head><meta http-equiv="Content-Security-Policy" content="script-src 'strict-dynamic' 'nonce-NONCE'; style-src 'nonce-NONCE';" />
-<script type="text/javascript" src="../resource/org.apache.wicket.resource.JQueryResourceReference/jquery/jquery-3.4.1.js" nonce="NONCE"></script>
+ <head><script type="text/javascript" src="../resource/org.apache.wicket.resource.JQueryResourceReference/jquery/jquery-3.4.1.js" nonce="NONCE"></script>
<script type="text/javascript" src="../resource/org.apache.wicket.ajax.AbstractDefaultAjaxBehavior/res/js/wicket-ajax-jquery.js" nonce="NONCE"></script>
<script type="text/javascript" id="wicket-ajax-debug-enable" nonce="NONCE">
/*<![CDATA[*/
diff --git a/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/FilteringHeaderResponseTest.java b/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/FilteringHeaderResponseTest.java
index 63bbadf..2d5c467 100644
--- a/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/FilteringHeaderResponseTest.java
+++ b/wicket-core/src/test/java/org/apache/wicket/markup/head/filter/FilteringHeaderResponseTest.java
@@ -20,12 +20,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
import java.util.Collections;
+import org.apache.wicket.csp.CSPDirective;
+import org.apache.wicket.csp.ContentSecurityPolicyEnforcer;
import org.apache.wicket.markup.head.IHeaderResponse;
import org.apache.wicket.markup.head.ResourceAggregator;
import org.apache.wicket.markup.head.StringHeaderItem;
import org.apache.wicket.markup.head.internal.HeaderResponse;
import org.apache.wicket.markup.html.IHeaderResponseDecorator;
+import org.apache.wicket.mock.MockApplication;
+import org.apache.wicket.protocol.http.WebApplication;
import org.apache.wicket.request.Response;
+import org.apache.wicket.request.cycle.RequestCycle;
import org.apache.wicket.response.StringResponse;
import org.apache.wicket.util.tester.WicketTestCase;
import org.junit.jupiter.api.Test;
@@ -37,6 +42,25 @@ import org.junit.jupiter.api.Test;
*/
class FilteringHeaderResponseTest extends WicketTestCase
{
+ @Override
+ protected WebApplication newApplication()
+ {
+ return new MockApplication()
+ {
+ @Override
+ protected ContentSecurityPolicyEnforcer newCspEnforcer()
+ {
+ return new ContentSecurityPolicyEnforcer(this)
+ {
+ @Override
+ public String getNonce(RequestCycle cycle)
+ {
+ return "NONCE";
+ }
+ };
+ }
+ };
+ }
@Test
void footerDependsOnHeadItem() throws Exception
@@ -96,9 +120,7 @@ class FilteringHeaderResponseTest extends WicketTestCase
@Test
void nonce() throws Exception
{
- tester.getApplication()
- .getHeaderResponseDecorators()
- .add(response -> new CspNonceHeaderResponse(response, "NONCE"));
+ tester.getApplication().getCsp().blocking().strict();
executeTest(CspNoncePage.class, "CspNoncePageExpected.html");
}
}
diff --git a/wicket-examples/src/main/java/org/apache/wicket/examples/csp/CspApplication.java b/wicket-examples/src/main/java/org/apache/wicket/examples/csp/CspApplication.java
index e8eff7e..ae9187d 100644
--- a/wicket-examples/src/main/java/org/apache/wicket/examples/csp/CspApplication.java
+++ b/wicket-examples/src/main/java/org/apache/wicket/examples/csp/CspApplication.java
@@ -16,24 +16,11 @@
*/
package org.apache.wicket.examples.csp;
-import java.util.Base64;
-import java.util.concurrent.ThreadLocalRandom;
-
-import org.apache.wicket.MetaDataKey;
import org.apache.wicket.Page;
-import org.apache.wicket.Session;
import org.apache.wicket.examples.WicketExampleApplication;
-import org.apache.wicket.markup.head.ResourceAggregator;
-import org.apache.wicket.markup.head.filter.CspNonceHeaderResponse;
public class CspApplication extends WicketExampleApplication
{
- private static final int NONCE_LENGTH = 24;
-
- public static MetaDataKey<String> NONCE_KEY = new MetaDataKey<String>()
- {
- };
-
@Override
public Class<? extends Page> getHomePage()
{
@@ -45,28 +32,8 @@ public class CspApplication extends WicketExampleApplication
{
super.init();
- getHeaderResponseDecorators().add(response -> new CspNonceHeaderResponse(response, getNonce()));
+ getCsp().blocking().strict();
mountPage("noncedemo", NonceDemoPage.class);
}
-
- protected static String generateNonce()
- {
- byte[] randomBytes = new byte[NONCE_LENGTH];
- ThreadLocalRandom.current().nextBytes(randomBytes);
- return Base64.getUrlEncoder().encodeToString(randomBytes);
- }
-
- public static String getNonce()
- {
- Session session = Session.get();
- session.bind();
- String nonce = session.getMetaData(NONCE_KEY);
- if (nonce == null)
- {
- nonce = generateNonce();
- session.setMetaData(NONCE_KEY, nonce);
- }
- return nonce;
- }
}