You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by mg...@apache.org on 2015/04/10 15:51:53 UTC

[6/6] wicket git commit: WICKET-5860 Cross-Site Websocket Hijacking protection

WICKET-5860 Cross-Site Websocket Hijacking protection


Project: http://git-wip-us.apache.org/repos/asf/wicket/repo
Commit: http://git-wip-us.apache.org/repos/asf/wicket/commit/4f7c7b35
Tree: http://git-wip-us.apache.org/repos/asf/wicket/tree/4f7c7b35
Diff: http://git-wip-us.apache.org/repos/asf/wicket/diff/4f7c7b35

Branch: refs/heads/master
Commit: 4f7c7b351b89fad5c49b8e71ab5489ac5f2c1a29
Parents: f6ddba3
Author: Martin Tzvetanov Grigorov <mg...@apache.org>
Authored: Fri Apr 10 16:44:45 2015 +0300
Committer: Martin Tzvetanov Grigorov <mg...@apache.org>
Committed: Fri Apr 10 16:51:35 2015 +0300

----------------------------------------------------------------------
 .../wicket/protocol/ws/WebSocketSettings.java   | 110 +++------
 .../ws/api/AbstractWebSocketProcessor.java      |  56 +++--
 .../protocol/ws/api/ConnectionRejected.java     |  48 ++++
 .../ws/api/ConnectionRejectedException.java     |  38 ---
 .../protocol/ws/api/FilterCollection.java       |  80 -------
 .../ws/api/IWebSocketConnectionFilter.java      |   4 +-
 .../protocol/ws/api/ServletRequestCopy.java     |  34 ++-
 .../protocol/ws/api/WebSocketBehavior.java      |  14 +-
 .../WebSocketConnectionFilterCollection.java    |  24 +-
 .../ws/api/WebSocketConnectionOriginFilter.java | 138 +++++++----
 .../protocol/ws/api/WebSocketResource.java      |  12 +-
 .../ws/api/event/WebSocketAbortedPayload.java   |  23 +-
 .../protocol/ws/api/message/AbortedMessage.java |  40 +---
 .../ws/api/message/AbstractClientMessage.java   |  54 +++++
 .../protocol/ws/api/message/ClosedMessage.java  |  26 +-
 .../ws/api/message/ConnectedMessage.java        |  26 +-
 .../ws/util/tester/TestWebSocketProcessor.java  |  26 +-
 .../ws/util/tester/TestWebSocketResource.java   |  10 +-
 .../tester/WebSocketTesterBehaviorTest.java     |   2 +-
 .../tester/WebSocketTesterProcessorTest.java    | 235 ++++++++++---------
 20 files changed, 480 insertions(+), 520 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/WebSocketSettings.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/WebSocketSettings.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/WebSocketSettings.java
index 5a13374..87bde1c 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/WebSocketSettings.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/WebSocketSettings.java
@@ -16,15 +16,14 @@
  */
 package org.apache.wicket.protocol.ws;
 
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
 import java.util.concurrent.Callable;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.MetaDataKey;
 import org.apache.wicket.Page;
 import org.apache.wicket.protocol.ws.api.IWebSocketConnection;
+import org.apache.wicket.protocol.ws.api.IWebSocketConnectionFilter;
+import org.apache.wicket.protocol.ws.api.WebSocketConnectionFilterCollection;
 import org.apache.wicket.protocol.ws.api.WebSocketRequestHandler;
 import org.apache.wicket.protocol.ws.api.WebSocketResponse;
 import org.apache.wicket.protocol.ws.api.registry.IWebSocketConnectionRegistry;
@@ -45,7 +44,7 @@ public class WebSocketSettings
 	};
 
 	/**
-	 * Holds this IWebSocketSettings in the Application's metadata.
+	 * Holds this WebSocketSettings in the Application's metadata.
 	 * This way wicket-core module doesn't have reference to wicket-native-websocket.
 	 */
 	public static final class Holder
@@ -90,14 +89,9 @@ public class WebSocketSettings
 	private IWebSocketConnectionRegistry connectionRegistry = new SimpleWebSocketConnectionRegistry();
 
 	/**
-	 * The whitelist of allowed domains where the client can connect to the application from
+	 * A filter that may reject an incoming connection
 	 */
-    private final List<String> allowedDomains = new ArrayList<String>();
-
-    /**
-     * Flag which indicates whether connection filtering should be active or not
-     */
-    private boolean protectionNeeded = false;
+	private IWebSocketConnectionFilter connectionFilter;
 
 	/**
 	 * Set the executor for processing websocket push messages broadcasted to all sessions.
@@ -115,16 +109,28 @@ public class WebSocketSettings
 	}
 
 	/**
-	 * The executor for processing websocket push messages broadcasted to all sessions.
-	 *
-	 * @return
-	 *            The executor used for processing push messages.
+	 * @return the executor for processing websocket push messages broadcasted to all sessions.
+	 */
+	public Executor getWebSocketPushMessageExecutor()
+	{
+		return webSocketPushMessageExecutor;
+	}
+
+	/**
+	 * @return The registry that tracks all currently connected WebSocket clients
 	 */
 	public IWebSocketConnectionRegistry getConnectionRegistry()
 	{
 		return connectionRegistry;
 	}
 
+	/**
+	 * Sets the connection registry
+	 *
+	 * @param connectionRegistry
+	 *              The registry that tracks all currently connected WebSocket clients
+	 * @return {@code this}, for method chaining
+	 */
 	public WebSocketSettings setConnectionRegistry(IWebSocketConnectionRegistry connectionRegistry)
 	{
 		Args.notNull(connectionRegistry, "connectionRegistry");
@@ -132,11 +138,6 @@ public class WebSocketSettings
 		return this;
 	}
 
-	public Executor getWebSocketPushMessageExecutor()
-	{
-		return webSocketPushMessageExecutor;
-	}
-
 	/**
 	 * The executor that broadcasts the {@link org.apache.wicket.protocol.ws.api.event.WebSocketPayload}
 	 * via Wicket's event bus.
@@ -165,60 +166,27 @@ public class WebSocketSettings
 	 */
 	public Executor getSendPayloadExecutor()
 	{
-		return sendPayloadExecutor;
+	return sendPayloadExecutor;
 	}
 
-    /**
-     * Flag that controls whether hijacking protection should be turned on or not
-     *
-     * @param protectionNeeded
-     *            True if protection needed
-     */
-    public void setHijackingProtectionEnabled(boolean protectionNeeded) {
-        this.protectionNeeded = protectionNeeded;
-    }
-
-    /**
-     * Flag that shows whether hijacking protection is turned on or not
-     *
-     * @param protectionNeeded
-     *            True if protection turned on
-     */
-    public boolean isHijackingProtectionEnabled() {
-        return this.protectionNeeded;
-    }
-
-    /**
-     * The list of whitelisted domains which are allowed to initiate a websocket connection. This
-     * list will be eventually used by the
-     * {@link org.apache.wicket.protocol.ws.api.IWebSocketConnectionFilter} to abort potentially
-     * unsafe connections. Example domain names might be:
-     *
-     * <pre>
-     *      http://www.example.com
-     *      http://ww2.example.com
-     * </pre>
-     *
-     * @param domains
-     *            The collection of domains
-     */
-    public void setAllowedDomains(Collection<String> domains) {
-	this.allowedDomains.clear();
-        this.allowedDomains.addAll(domains);
-    }
+	/**
+	 * Sets the filter for checking the incoming connections
+	 * @param connectionFilter
+	 *              the filter for checking the incoming connections
+	 * @see WebSocketConnectionFilterCollection
+	 */
+	public void setConnectionFilter(IWebSocketConnectionFilter connectionFilter)
+	{
+		this.connectionFilter = connectionFilter;
+	}
 
-    /**
-     * The list of whitelisted domains which are allowed to initiate a websocket connection. This
-     * list will be eventually used by the
-     * {@link org.apache.wicket.protocol.ws.api.IWebSocketConnectionFilter} to abort potentially
-     * unsafe connections
-     *
-     * @param domains
-     *            The collection of domains if or an empty list when no domains were added
-     */
-    public List<String> getAllowedDomains() {
-        return this.allowedDomains;
-    }
+	/**
+	 * @return the filter for checking the incoming connections
+	 * @see WebSocketConnectionFilterCollection
+	 */
+	public IWebSocketConnectionFilter getConnectionFilter() {
+		return this.connectionFilter;
+	}
 
 	/**
 	 * A factory method for the {@link org.apache.wicket.request.http.WebResponse}

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
index 5d0e829..7126ee1 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/AbstractWebSocketProcessor.java
@@ -16,8 +16,6 @@
  */
 package org.apache.wicket.protocol.ws.api;
 
-import java.util.Collection;
-
 import javax.servlet.http.HttpServletRequest;
 
 import org.apache.wicket.Application;
@@ -88,8 +86,8 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
 	private final String sessionId;
 	private final WebSocketSettings webSocketSettings;
 	private final IWebSocketConnectionRegistry connectionRegistry;
-    private final WebSocketConnectionFilterCollection connectionFilters;
-    private final HttpServletRequest servletRequest;
+	private final IWebSocketConnectionFilter connectionFilter;
+	private final HttpServletRequest servletRequest;
 
 	/**
 	 * Constructor.
@@ -133,8 +131,7 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
 
 		this.connectionRegistry = webSocketSettings.getConnectionRegistry();
 
-        this.connectionFilters = new WebSocketConnectionFilterCollection();
-        connectionFilters.add(new WebSocketConnectionOriginFilter(webSocketSettings));
+		this.connectionFilter = webSocketSettings.getConnectionFilter();
 	}
 
 	@Override
@@ -150,25 +147,31 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
 		broadcastMessage(binaryMessage);
 	}
 
-    /**
-     * A helper that registers the opened connection in the application-level registry.
-     *
-     * @param connection
-     *            the web socket connection to use to communicate with the client
-     * @see #onOpen(Object)
-     */
-    protected final void onConnect(final IWebSocketConnection connection) {
-        IKey key = getRegistryKey();
-        try {
-            connectionRegistry.setConnection(getApplication(), getSessionId(), key, connection);
-            connectionFilters.doFilter(servletRequest);
-            broadcastMessage(new ConnectedMessage(getApplication(), getSessionId(), key));
-        } catch (ConnectionRejectedException e) {
-            broadcastMessage(new AbortedMessage(getApplication(), getSessionId(), key));
-            connectionRegistry.removeConnection(getApplication(), getSessionId(), key);
-            connection.close(e.getCode(), e.getReason());
-        }
-    }
+	/**
+	 * A helper that registers the opened connection in the application-level registry.
+	 *
+	 * @param connection
+	 *            the web socket connection to use to communicate with the client
+	 * @see #onOpen(Object)
+	 */
+	protected final void onConnect(final IWebSocketConnection connection) {
+		IKey key = getRegistryKey();
+		connectionRegistry.setConnection(getApplication(), getSessionId(), key, connection);
+
+		if (connectionFilter != null)
+		{
+			ConnectionRejected connectionRejected = connectionFilter.doFilter(servletRequest);
+			if (connectionRejected != null)
+			{
+				broadcastMessage(new AbortedMessage(getApplication(), getSessionId(), key));
+				connectionRegistry.removeConnection(getApplication(), getSessionId(), key);
+				connection.close(connectionRejected.getCode(), connectionRejected.getReason());
+				return;
+			}
+		}
+
+		broadcastMessage(new ConnectedMessage(getApplication(), getSessionId(), key));
+	}
 
 	@Override
 	public void onClose(int closeCode, String message)
@@ -332,7 +335,8 @@ public abstract class AbstractWebSocketProcessor implements IWebSocketProcessor
 		{
 			payload = new WebSocketClosedPayload((ClosedMessage) message, handler);
 		}
-		else if (message instanceof AbortedMessage) {
+		else if (message instanceof AbortedMessage)
+		{
 			payload = new WebSocketAbortedPayload((AbortedMessage) message, handler);
 		}
 		else if (message instanceof IWebSocketPushMessage)

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ConnectionRejected.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ConnectionRejected.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ConnectionRejected.java
new file mode 100644
index 0000000..90af93d
--- /dev/null
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ConnectionRejected.java
@@ -0,0 +1,48 @@
+/*
+ * 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.protocol.ws.api;
+
+/**
+ * A class used by {@link IWebSocketConnectionFilter}s when they need to reject a connection
+ */
+public class ConnectionRejected
+{
+	private final int code;
+	private final String reason;
+
+	/**
+	 * Constructor
+	 *
+	 * @param code
+	 *              The error code
+	 * @param reason
+	 *              The reason to reject the connection
+	 */
+    public ConnectionRejected(int code, String reason)
+    {
+		this.code = code;
+		this.reason = reason;
+    }
+
+	public int getCode() {
+		return code;
+	}
+
+	public String getReason() {
+		return reason;
+	}
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ConnectionRejectedException.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ConnectionRejectedException.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ConnectionRejectedException.java
deleted file mode 100644
index 16834f4..0000000
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ConnectionRejectedException.java
+++ /dev/null
@@ -1,38 +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.protocol.ws.api;
-
-public class ConnectionRejectedException extends RuntimeException {
-
-	private static final long serialVersionUID = 4552012810343573564L;
-
-	private final int code;
-	private final String reason;
-
-    public ConnectionRejectedException(int code, String reason) {
-		this.code = code;
-		this.reason = reason;
-    }
-
-	public int getCode() {
-		return code;
-	}
-
-	public String getReason() {
-		return reason;
-	}
-}

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/FilterCollection.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/FilterCollection.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/FilterCollection.java
deleted file mode 100644
index 8b08d89..0000000
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/FilterCollection.java
+++ /dev/null
@@ -1,80 +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.protocol.ws.api;
-
-import java.io.Serializable;
-import java.util.Iterator;
-import java.util.List;
-import java.util.concurrent.CopyOnWriteArrayList;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Represents a collection of filters. Facilitates invocation of filtering on each filter.
- *
- * @author Gergely Nagy
- *
- * @param <T>
- *            type of filters
- */
-public class FilterCollection<T> implements Serializable, Iterable<T> {
-
-	private static final long serialVersionUID = -7389583130277632264L;
-
-	/** list of listeners */
-	private final List<T> filters = new CopyOnWriteArrayList<>();
-
-	/**
-	 * Adds a filter to this set of filters.
-	 *
-	 * @param filter
-	 *            The filter to add
-	 * @return {@code true} if the filter was added
-	 */
-	public boolean add(final T filter)
-	{
-		if (filter == null)
-		{
-			return false;
-		}
-		filters.add(filter);
-		return true;
-	}
-
-	/**
-	 * Removes a filter from this set.
-	 *
-	 * @param filter
-	 *            The filter to remove
-	 */
-	public void remove(final T filter)
-	{
-		filters.remove(filter);
-	}
-
-	/**
-	 * Returns an iterator that can iterate the filter.
-	 *
-	 * @return an iterator that can iterate the filters.
-	 */
-	@Override
-	public Iterator<T> iterator() {
-		return filters.iterator();
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/IWebSocketConnectionFilter.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/IWebSocketConnectionFilter.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/IWebSocketConnectionFilter.java
index a43c7c1..afd0f2e 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/IWebSocketConnectionFilter.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/IWebSocketConnectionFilter.java
@@ -23,8 +23,8 @@ import javax.servlet.http.HttpServletRequest;
  * One example might be when the connection 'Origin' header does not match the origin of the
  * application host
  *
+ * @see WebSocketConnectionFilterCollection
  * @author Gergely Nagy
- *
  */
 public interface IWebSocketConnectionFilter {
 
@@ -34,5 +34,5 @@ public interface IWebSocketConnectionFilter {
      * @param servletRequest
      *            The servlet request holding the request headers
      */
-    public void doFilter(HttpServletRequest servletRequest);
+    ConnectionRejected doFilter(HttpServletRequest servletRequest);
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ServletRequestCopy.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ServletRequestCopy.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ServletRequestCopy.java
index bffc301..218b1f7 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ServletRequestCopy.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/ServletRequestCopy.java
@@ -58,7 +58,7 @@ public class ServletRequestCopy implements HttpServletRequest
 	private final HttpSessionCopy httpSession;
 	private final StringBuffer requestURL;
 	private final Map<String, Object> attributes = new HashMap<>();
-	private final Map<String, String> headers = new HashMap<>();
+	private final Map<String, Enumeration<String>> headers = new HashMap<>();
 	private final Map<String, String[]> parameters = new HashMap<>();
 	private final String method;
 	private final String serverName;
@@ -81,7 +81,8 @@ public class ServletRequestCopy implements HttpServletRequest
 		Enumeration<String> e = request.getHeaderNames();
 		while (e != null && e.hasMoreElements()) {
 			s = e.nextElement();
-			headers.put(s, request.getHeader(s));
+			Enumeration<String> headerValues = request.getHeaders(s);
+			this.headers.put(s, headerValues);
 		}
 
 		e = request.getAttributeNames();
@@ -154,27 +155,20 @@ public class ServletRequestCopy implements HttpServletRequest
 	}
 
 	@Override
-	public String getHeader(String name) {
-		return headers.get(name);
+	public String getHeader(String name)
+	{
+		Enumeration<String> values = headers.get(name);
+		if (values != null && values.hasMoreElements())
+		{
+			return values.nextElement();
+		}
+		return null;
 	}
 
 	@Override
-	public Enumeration<String> getHeaders(final String name) {
-		return new Enumeration<String>() {
-
-			boolean hasNext = true;
-
-			@Override
-			public boolean hasMoreElements() {
-				return hasNext && headers.get(name) != null;
-			}
-
-			@Override
-			public String nextElement() {
-				hasNext = false;
-				return headers.get(name);
-			}
-		};
+	public Enumeration<String> getHeaders(final String name)
+	{
+		return headers.get(name);
 	}
 
 	@Override

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java
index 803246d..50cb5f0 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketBehavior.java
@@ -79,12 +79,12 @@ public abstract class WebSocketBehavior extends BaseWebSocketBehavior
 				ClosedMessage message = closedPayload.getMessage();
 				onClose(message);
 			}
-            else if (wsPayload instanceof WebSocketAbortedPayload)
-            {
-                WebSocketAbortedPayload abortedPayload = (WebSocketAbortedPayload) wsPayload;
-                AbortedMessage message = abortedPayload.getMessage();
-                onAbort(message);
-            }
+			else if (wsPayload instanceof WebSocketAbortedPayload)
+			{
+				WebSocketAbortedPayload abortedPayload = (WebSocketAbortedPayload) wsPayload;
+				AbortedMessage message = abortedPayload.getMessage();
+				onAbort(message);
+			}
 			else if (wsPayload instanceof WebSocketPushPayload)
 			{
 				WebSocketPushPayload pushPayload = (WebSocketPushPayload) wsPayload;
@@ -133,7 +133,7 @@ public abstract class WebSocketBehavior extends BaseWebSocketBehavior
      * A callback method called when the server has aborted the connection
      *
      * @param message
-     *          the aborted message with the info about the server
+     *          the aborted message with the info about the client
      */
     protected void onAbort(AbortedMessage message) {
     }

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionFilterCollection.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionFilterCollection.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionFilterCollection.java
index 63a9bc6..4257edd 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionFilterCollection.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionFilterCollection.java
@@ -16,19 +16,27 @@
  */
 package org.apache.wicket.protocol.ws.api;
 
-import javax.servlet.http.HttpServletRequest;
+import java.util.ArrayList;
 
-public class WebSocketConnectionFilterCollection extends
-		FilterCollection<IWebSocketConnectionFilter> implements
-		IWebSocketConnectionFilter {
+import javax.servlet.http.HttpServletRequest;
 
-	private static final long serialVersionUID = 3953951891780895469L;
+public class WebSocketConnectionFilterCollection extends ArrayList<IWebSocketConnectionFilter>
+		implements IWebSocketConnectionFilter
+{
+	private static final long serialVersionUID = 1L;
 
 	@Override
-	public void doFilter(HttpServletRequest servletRequest) {
-		for (IWebSocketConnectionFilter filter : this) {
-			filter.doFilter(servletRequest);
+	public ConnectionRejected doFilter(final HttpServletRequest servletRequest)
+	{
+		for (IWebSocketConnectionFilter filter : this)
+		{
+			ConnectionRejected connectionRejected = filter.doFilter(servletRequest);
+			if (connectionRejected != null)
+			{
+				return connectionRejected;
+			}
 		}
+		return null;
 	}
 
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionOriginFilter.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionOriginFilter.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionOriginFilter.java
index bc08c98..fdf0ef2 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionOriginFilter.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketConnectionOriginFilter.java
@@ -16,13 +16,14 @@
  */
 package org.apache.wicket.protocol.ws.api;
 
-import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Enumeration;
 import java.util.List;
 
 import javax.servlet.http.HttpServletRequest;
 
-import org.apache.wicket.protocol.ws.WebSocketSettings;
+import org.apache.wicket.util.lang.Args;
+import org.apache.wicket.util.string.Strings;
 
 /**
  * This filter will reject those requests which contain 'Origin' header that does not match the origin of the
@@ -32,57 +33,104 @@ import org.apache.wicket.protocol.ws.WebSocketSettings;
  * @see <a href="http://www.christian-schneider.net/CrossSiteWebSocketHijacking.html">http://www.christian-schneider.net/CrossSiteWebSocketHijacking.html</a>
  *
  * @author Gergely Nagy
- *
  */
-public class WebSocketConnectionOriginFilter implements IWebSocketConnectionFilter {
+public class WebSocketConnectionOriginFilter implements IWebSocketConnectionFilter
+{
+
+	/**
+	 * Error code 1008 indicates that an endpoint is terminating the connection because it has received a message that
+     * violates its policy. This is a generic status code that can be returned when there is no other more suitable
+     * status code (e.g., 1003 or 1009) or if there is a need to hide specific details about the policy.
+	 * <p>
+	 * See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
+	 */
+	public static final int POLICY_VIOLATION_ERROR_CODE = 1008;
+
+	/**
+	 * Explanatory text for the client to explain why the connection is getting aborted
+	 */
+	public static final String ORIGIN_MISMATCH = "Origin mismatch";
 
-    /**
-     * 1008 indicates that an endpoint is terminating the connection because it has received a message that violates its policy. This is a generic status code
-     * that can be returned when there is no other more suitable status code (e.g., 1003 or 1009) or if there is a need to hide specific details about the
-     * policy.
-     * <p>
-     * See <a href="https://tools.ietf.org/html/rfc6455#section-7.4.1">RFC 6455, Section 7.4.1 Defined Status Codes</a>.
-     */
-    public static final int POLICY_VIOLATION = 1008;
+	private final List<String> allowedDomains;
 
-    /**
-     * Explanatory text for the client to explain why the connection is getting aborted
-     */
-    public static final String ORIGIN_MISMATCH = "Origin mismatch";
+	public WebSocketConnectionOriginFilter(final List<String> allowedDomains)
+	{
+		this.allowedDomains = Args.notNull(allowedDomains, "allowedDomains");
+	}
 
-    private final WebSocketSettings webSocketSettings;
+	@Override
+	public ConnectionRejected doFilter(HttpServletRequest servletRequest)
+	{
+		if (allowedDomains != null && !allowedDomains.isEmpty())
+		{
+			String oUrl = getOriginUrl(servletRequest);
+			if (invalid(oUrl, allowedDomains))
+			{
+				return new ConnectionRejected(POLICY_VIOLATION_ERROR_CODE, ORIGIN_MISMATCH);
+			}
+		}
 
-    public WebSocketConnectionOriginFilter(WebSocketSettings webSocketSettings) {
-        this.webSocketSettings = webSocketSettings;
-    }
+		return null;
+	}
 
-    @Override
-    public void doFilter(HttpServletRequest servletRequest) {
-        if (webSocketSettings.isHijackingProtectionEnabled()) {
-            String oUrl = getOriginUrl(servletRequest);
-            if (invalid(oUrl))
-                throw new ConnectionRejectedException(POLICY_VIOLATION, ORIGIN_MISMATCH);
-        }
-    }
+	/**
+	 * The list of whitelisted domains which are allowed to initiate a websocket connection. This
+	 * list will be eventually used by the
+	 * {@link org.apache.wicket.protocol.ws.api.IWebSocketConnectionFilter} to abort potentially
+	 * unsafe connections. Example domain names might be:
+	 *
+	 * <pre>
+	 *      http://www.example.com
+	 *      http://ww2.example.com
+	 * </pre>
+	 *
+	 * @param domains
+	 *            The collection of domains
+	 */
+	public void setAllowedDomains(Iterable<String> domains) {
+		this.allowedDomains.clear();
+		if (domains != null)
+		{
+			for (String domain : domains)
+			{
+				this.allowedDomains.add(domain);
+			}
+		}
+	}
 
-    private boolean invalid(String oUrl) {
-        if (originMismatch(oUrl))
-            return true;
-        if (oUrl == null || "".equals(oUrl))
-            return true;
-        return false;
-    }
+	/**
+	 * The list of whitelisted domains which are allowed to initiate a websocket connection. This
+	 * list will be eventually used by the
+	 * {@link org.apache.wicket.protocol.ws.api.IWebSocketConnectionFilter} to abort potentially
+	 * unsafe connections
+	 */
+	public List<String> getAllowedDomains()
+	{
+		return allowedDomains;
+	}
 
-    private boolean originMismatch(String oUrl) {
-        List<String> allowedDomains = webSocketSettings.getAllowedDomains();
-        return !allowedDomains.contains(oUrl);
-    }
+	private boolean invalid(String oUrl, List<String> allowedDomains)
+	{
+		return Strings.isEmpty(oUrl) || !allowedDomains.contains(oUrl);
+	}
 
-    private String getOriginUrl(HttpServletRequest servletRequest) {
-        ArrayList<String> origins = Collections.list(servletRequest.getHeaders("Origin"));
-        if (origins.size() != 1)
-            return null;
-        return origins.get(0);
-    }
+	private String getOriginUrl(final HttpServletRequest servletRequest)
+	{
+		Enumeration<String> originHeaderValues = servletRequest.getHeaders("Origin");
+		List<String> origins;
+		if (originHeaderValues != null)
+		{
+			origins = Collections.list(originHeaderValues);
+		}
+		else
+		{
+			origins = Collections.emptyList();
+		}
 
+		if (origins.size() != 1)
+		{
+			return null;
+		}
+		return origins.get(0);
+	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java
index 95aed1d..a49fc2b 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/WebSocketResource.java
@@ -64,12 +64,12 @@ public abstract class WebSocketResource implements IResource
 			ClosedMessage message = connectedPayload.getMessage();
 			onClose(message);
 		}
-        else if (payload instanceof WebSocketAbortedPayload)
-        {
-            WebSocketAbortedPayload abortedPayload = (WebSocketAbortedPayload) payload;
-            AbortedMessage message = abortedPayload.getMessage();
-            onAbort(message);
-        }
+		else if (payload instanceof WebSocketAbortedPayload)
+		{
+			WebSocketAbortedPayload abortedPayload = (WebSocketAbortedPayload) payload;
+			AbortedMessage message = abortedPayload.getMessage();
+			onAbort(message);
+		}
 		else if (payload instanceof WebSocketPushPayload)
 		{
 			WebSocketPushPayload pushPayload = (WebSocketPushPayload) payload;

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/event/WebSocketAbortedPayload.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/event/WebSocketAbortedPayload.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/event/WebSocketAbortedPayload.java
index f19aa95..399b959 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/event/WebSocketAbortedPayload.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/event/WebSocketAbortedPayload.java
@@ -24,19 +24,18 @@ import org.apache.wicket.protocol.ws.api.message.AbortedMessage;
  *
  * @since 7.0.0-M5
  */
-public class WebSocketAbortedPayload extends WebSocketPayload<AbortedMessage> {
+public class WebSocketAbortedPayload extends WebSocketPayload<AbortedMessage>
+{
+	private final AbortedMessage message;
 
-    private final AbortedMessage message;
+	public WebSocketAbortedPayload(AbortedMessage message, WebSocketRequestHandler handler) {
+		super(handler);
 
-    public WebSocketAbortedPayload(AbortedMessage message, WebSocketRequestHandler handler) {
-        super(handler);
-
-        this.message = message;
-    }
-
-    @Override
-    public AbortedMessage getMessage() {
-        return message;
-    }
+		this.message = message;
+	}
 
+	@Override
+	public AbortedMessage getMessage() {
+		return message;
+	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/AbortedMessage.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/AbortedMessage.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/AbortedMessage.java
index 2040554..61cc13e 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/AbortedMessage.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/AbortedMessage.java
@@ -18,39 +18,21 @@ package org.apache.wicket.protocol.ws.api.message;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.protocol.ws.api.registry.IKey;
-import org.apache.wicket.util.lang.Args;
 
 /**
  * A {@link IWebSocketMessage message} sent when the web socket connection is aborted.
  *
  * @since 7.0.0-M5
  */
-public class AbortedMessage implements IWebSocketMessage {
-
-    private final Application application;
-    private final String sessionId;
-    private final IKey key;
-
-    public AbortedMessage(Application application, String sessionId, IKey key) {
-        this.application = Args.notNull(application, "application");
-        this.sessionId = Args.notNull(sessionId, "sessionId");
-        this.key = Args.notNull(key, "key");
-    }
-
-    public Application getApplication() {
-        return application;
-    }
-
-    public String getSessionId() {
-        return sessionId;
-    }
-
-    public IKey getKey() {
-        return key;
-    }
-
-    @Override
-    public final String toString() {
-        return "The server aborted the client connection";
-    }
+public class AbortedMessage extends AbstractClientMessage
+{
+	public AbortedMessage(Application application, String sessionId, IKey key)
+	{
+		super(application, sessionId, key);
+	}
+
+	@Override
+	public final String toString() {
+		return "The server aborted the client connection";
+	}
 }

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/AbstractClientMessage.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/AbstractClientMessage.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/AbstractClientMessage.java
new file mode 100644
index 0000000..7e3234c
--- /dev/null
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/AbstractClientMessage.java
@@ -0,0 +1,54 @@
+/*
+ * 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.protocol.ws.api.message;
+
+import org.apache.wicket.Application;
+import org.apache.wicket.protocol.ws.api.registry.IKey;
+import org.apache.wicket.util.lang.Args;
+
+/**
+ * A base message for all messages with information about the client
+ */
+public abstract class AbstractClientMessage implements IWebSocketMessage
+{
+	private final Application application;
+	private final String sessionId;
+	private final IKey key;
+
+	public AbstractClientMessage(Application application, String sessionId, IKey key)
+	{
+		this.application = Args.notNull(application, "application");
+		this.sessionId = Args.notNull(sessionId, "sessionId");
+		this.key = Args.notNull(key, "key");
+	}
+
+	public Application getApplication()
+	{
+		return application;
+	}
+
+	public String getSessionId()
+	{
+		return sessionId;
+	}
+
+	public IKey getKey()
+	{
+		return key;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ClosedMessage.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ClosedMessage.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ClosedMessage.java
index 43046c0..9dad746 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ClosedMessage.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ClosedMessage.java
@@ -18,7 +18,6 @@ package org.apache.wicket.protocol.ws.api.message;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.protocol.ws.api.registry.IKey;
-import org.apache.wicket.util.lang.Args;
 
 /**
  * A {@link IWebSocketMessage message} sent when the web socket connection
@@ -26,32 +25,11 @@ import org.apache.wicket.util.lang.Args;
  *
  * @since 6.0
  */
-public class ClosedMessage implements IWebSocketMessage
+public class ClosedMessage extends AbstractClientMessage
 {
-	private final Application application;
-	private final String sessionId;
-	private final IKey key;
-
 	public ClosedMessage(Application application, String sessionId, IKey key)
 	{
-		this.application = Args.notNull(application, "application");
-		this.sessionId = Args.notNull(sessionId, "sessionId");
-		this.key = Args.notNull(key, "key");
-	}
-
-	public Application getApplication()
-	{
-		return application;
-	}
-
-	public String getSessionId()
-	{
-		return sessionId;
-	}
-
-	public IKey getKey()
-	{
-		return key;
+		super(application, sessionId, key);
 	}
 
 	@Override

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ConnectedMessage.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ConnectedMessage.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ConnectedMessage.java
index ab085ce..8e0485f 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ConnectedMessage.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/api/message/ConnectedMessage.java
@@ -18,7 +18,6 @@ package org.apache.wicket.protocol.ws.api.message;
 
 import org.apache.wicket.Application;
 import org.apache.wicket.protocol.ws.api.registry.IKey;
-import org.apache.wicket.util.lang.Args;
 
 /**
  * A {@link IWebSocketMessage message} when a client creates web socket
@@ -26,32 +25,11 @@ import org.apache.wicket.util.lang.Args;
  *
  * @since 6.0
  */
-public class ConnectedMessage implements IWebSocketMessage
+public class ConnectedMessage extends AbstractClientMessage
 {
-	private final Application application;
-	private final String sessionId;
-	private final IKey key;
-
 	public ConnectedMessage(Application application, String sessionId, IKey key)
 	{
-		this.application = Args.notNull(application, "application");
-		this.sessionId = Args.notNull(sessionId, "sessionId");
-		this.key = Args.notNull(key, "key");
-	}
-
-	public Application getApplication()
-	{
-		return application;
-	}
-
-	public String getSessionId()
-	{
-		return sessionId;
-	}
-
-	public IKey getKey()
-	{
-		return key;
+		super(application, sessionId, key);
 	}
 
 	@Override

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java
index 1ae8789..f7b55e1 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/main/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketProcessor.java
@@ -36,19 +36,19 @@ import org.apache.wicket.util.tester.WicketTester;
  */
 abstract class TestWebSocketProcessor extends AbstractWebSocketProcessor
 {
-    /**
-     *
-     * Constructor.
-     *
-     * @param request
-     *            the http request that was used to create the TomcatWebSocketProcessor
-     * @param application
-     *            the current Wicket Application
-     */
-    public TestWebSocketProcessor(final HttpServletRequest request, final WebApplication application)
-    {
-        super(request, application);
-    }
+	/**
+	 *
+	 * Constructor.
+	 *
+	 * @param request
+	 *            the http request that was used to create the IWebSocketProcessor
+	 * @param application
+	 *            the current Wicket Application
+	 */
+	public TestWebSocketProcessor(final HttpServletRequest request, final WebApplication application)
+	{
+		super(request, application);
+	}
 
 	/**
 	 * Constructor.

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketResource.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketResource.java b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketResource.java
index 942889d..276c566 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketResource.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/TestWebSocketResource.java
@@ -78,11 +78,11 @@ public class TestWebSocketResource extends WebSocketResource
 		super.onClose(message);
 	}
 
-    @Override
-    protected void onAbort(AbortedMessage message) {
-        ON_ABORT_CALLED.set(true);
-        super.onAbort(message);
-    }
+	@Override
+	protected void onAbort(AbortedMessage message) {
+		ON_ABORT_CALLED.set(true);
+		super.onAbort(message);
+	}
 
 	@Override
 	protected void onMessage(WebSocketRequestHandler handler, TextMessage message)

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java
index c6516cb..241047e 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterBehaviorTest.java
@@ -137,7 +137,7 @@ public class WebSocketTesterBehaviorTest extends Assert
 		webSocketTester.broadcast(tester.getApplication(), tester.getHttpSession().getId(),
 				new PageIdKey(page.getPageId()), broadcastMessage);
 
-		assertEquals(true, messageReceived.get());
+		assertTrue(messageReceived.get());
 		webSocketTester.destroy();
 	}
 

http://git-wip-us.apache.org/repos/asf/wicket/blob/4f7c7b35/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterProcessorTest.java
----------------------------------------------------------------------
diff --git a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterProcessorTest.java b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterProcessorTest.java
index cf9fa80..5956299 100644
--- a/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterProcessorTest.java
+++ b/wicket-native-websocket/wicket-native-websocket-core/src/test/java/org/apache/wicket/protocol/ws/util/tester/WebSocketTesterProcessorTest.java
@@ -25,119 +25,136 @@ import org.apache.wicket.mock.MockApplication;
 import org.apache.wicket.protocol.http.WebApplication;
 import org.apache.wicket.protocol.http.mock.MockHttpServletRequest;
 import org.apache.wicket.protocol.ws.WebSocketSettings;
+import org.apache.wicket.protocol.ws.api.WebSocketConnectionOriginFilter;
 import org.apache.wicket.request.http.WebRequest;
 import org.apache.wicket.util.tester.WicketTester;
 import org.junit.After;
 import org.junit.Assert;
 import org.junit.Before;
-import org.junit.Ignore;
 import org.junit.Test;
 
-public class WebSocketTesterProcessorTest extends Assert {
-
-    final static AtomicBoolean messageReceived = new AtomicBoolean(false);
-
-    private static class TestProcessor extends TestWebSocketProcessor {
-        private TestProcessor(HttpServletRequest request, WebApplication application) {
-            super(request, application);
-        }
-
-        @Override
-        protected void onOutMessage(String message) {
-            messageReceived.set(true);
-        }
-
-        @Override
-        protected void onOutMessage(byte[] message, int offset, int length) {
-            messageReceived.set(true);
-        }
-    }
-
-    WicketTester tester;
-    WebApplication application = new MockApplication() {
-        @Override
-        protected void init() {
-            super.init();
-
-            getSharedResources().add(TestWebSocketResource.TEXT, new TestWebSocketResource("expected"));
-        }
-    };
-
-    @Before
-    public void before() {
-        tester = new WicketTester(application);
-        application.getWicketFilter().setFilterPath("");
-    }
-
-    @After
-    public void after() {
-        tester.destroy();
-        TestWebSocketResource.ON_ABORT_CALLED.set(false);
-    }
-
-    @Test
-    public void onConnectNoOrigin() throws Exception {
-        // Given header 'Origin' is missing
-        configureRequest(true, new String[] { "http://www.example.com" }, new String[] {});
-
-        // When we open a connection
-        TestWebSocketProcessor processor = new TestProcessor(tester.getRequest(), tester.getApplication());
-        processor.onOpen(new Object());
-
-        // Then it fails
-        assertEquals(true, TestWebSocketResource.ON_ABORT_CALLED.get());
-    }
-
-    @Ignore
-    @Test
-    public void onConnectMultipleOrigins() throws Exception {
-        // Given the request contains multiple header 'Origin's
-        configureRequest(true, new String[] { "http://www.example.com" }, new String[] { "http://www.example.com", "http://ww2.example.com" });
-
-        // When we open a connection
-        TestWebSocketProcessor processor = new TestProcessor(tester.getRequest(), tester.getApplication());
-        processor.onOpen(new Object());
-
-        // Then it fails
-        assertEquals(true, TestWebSocketResource.ON_ABORT_CALLED.get());
-    }
-
-    @Test
-    public void onConnectMatchingOrigin() throws Exception {
-        // Given header 'Origin' matches the host origin
-        configureRequest(true, new String[] { "http://www.example.com" }, new String[] { "http://www.example.com" });
-
-        // When we open a connection
-        TestWebSocketProcessor processor = new TestProcessor(tester.getRequest(), tester.getApplication());
-        processor.onOpen(new Object());
-
-        // Then it succeeds
-        assertEquals(false, TestWebSocketResource.ON_ABORT_CALLED.get());
-    }
-
-    @Test
-    public void onConnectMismatchingOrigin() throws Exception {
-        // Given header 'Origin' does not match the host origin
-        configureRequest(true, new String[] { "http://www.example.com" }, new String[] { "http://ww2.example.com" });
-
-        // When we open a connection
-        TestWebSocketProcessor processor = new TestProcessor(tester.getRequest(), tester.getApplication());
-        processor.onOpen(new Object());
-
-        // Then it fails
-        assertEquals(true, TestWebSocketResource.ON_ABORT_CALLED.get());
-    }
-
-    protected void configureRequest(boolean protectionNeeded, String[] allowedDomains, String[] origins) {
-        WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application);
-        webSocketSettings.setHijackingProtectionEnabled(protectionNeeded);
-        webSocketSettings.setAllowedDomains(Arrays.asList(allowedDomains));
-        MockHttpServletRequest request = tester.getRequest();
-        for (String origin : origins) {
-            request.addHeader("Origin", origin);
-        }
-        request.addParameter("resourceName", TestWebSocketResource.TEXT);
-        request.addParameter(WebRequest.PARAM_AJAX_BASE_URL, ".");
-    }
-
-}
\ No newline at end of file
+/**
+ * Tests for https://issues.apache.org/jira/browse/WICKET-5860
+ */
+public class WebSocketTesterProcessorTest extends Assert
+{
+	final static AtomicBoolean messageReceived = new AtomicBoolean(false);
+
+	private static class TestProcessor extends TestWebSocketProcessor
+	{
+		private TestProcessor(HttpServletRequest request, WebApplication application)
+		{
+			super(request, application);
+		}
+
+		@Override
+		protected void onOutMessage(String message)
+		{
+			messageReceived.set(true);
+		}
+
+		@Override
+		protected void onOutMessage(byte[] message, int offset, int length)
+		{
+			messageReceived.set(true);
+		}
+	}
+
+	WicketTester tester;
+	WebApplication application = new MockApplication()
+	{
+		@Override
+		protected void init()
+		{
+			super.init();
+
+			getSharedResources().add(TestWebSocketResource.TEXT, new TestWebSocketResource("expected"));
+		}
+	};
+
+	@Before
+	public void before()
+	{
+		tester = new WicketTester(application);
+		application.getWicketFilter().setFilterPath("");
+	}
+
+	@After
+	public void after()
+	{
+		tester.destroy();
+		TestWebSocketResource.ON_ABORT_CALLED.set(false);
+	}
+
+	@Test
+	public void onConnectNoOrigin()
+	{
+		// Given header 'Origin' is missing
+		configureRequest(new String[] { "http://www.example.com" }, new String[] {});
+
+		// When we open a connection
+		TestWebSocketProcessor processor = new TestProcessor(tester.getRequest(), tester.getApplication());
+		processor.onOpen(new Object());
+
+		// Then it fails
+		assertTrue(TestWebSocketResource.ON_ABORT_CALLED.get());
+	}
+
+//	@Ignore
+	@Test
+	public void onConnectMultipleOrigins()
+	{
+		// Given the request contains multiple header 'Origin's
+		configureRequest(new String[] { "http://www.example.com" }, new String[] { "http://www.example.com", "http://ww2.example.com" });
+
+		// When we open a connection
+		TestWebSocketProcessor processor = new TestProcessor(tester.getRequest(), tester.getApplication());
+		processor.onOpen(new Object());
+
+		// Then it fails
+		assertTrue(TestWebSocketResource.ON_ABORT_CALLED.get());
+	}
+
+	@Test
+	public void onConnectMatchingOrigin()
+	{
+		// Given header 'Origin' matches the host origin
+		configureRequest(new String[] { "http://www.example.com" }, new String[] { "http://www.example.com" });
+
+		// When we open a connection
+		TestWebSocketProcessor processor = new TestProcessor(tester.getRequest(), tester.getApplication());
+		processor.onOpen(new Object());
+
+		// Then it succeeds
+		assertFalse(TestWebSocketResource.ON_ABORT_CALLED.get());
+	}
+
+	@Test
+	public void onConnectMismatchingOrigin()
+	{
+		// Given header 'Origin' does not match the host origin
+		configureRequest(new String[] { "http://www.example.com" }, new String[] { "http://ww2.example.com" });
+
+		// When we open a connection
+		TestWebSocketProcessor processor = new TestProcessor(tester.getRequest(), tester.getApplication());
+		processor.onOpen(new Object());
+
+		// Then it fails
+		assertTrue(TestWebSocketResource.ON_ABORT_CALLED.get());
+	}
+
+	protected void configureRequest(String[] allowedDomains, String[] origins)
+	{
+		WebSocketSettings webSocketSettings = WebSocketSettings.Holder.get(application);
+		WebSocketConnectionOriginFilter connectionFilter = new WebSocketConnectionOriginFilter(Arrays.asList(allowedDomains));
+		webSocketSettings.setConnectionFilter(connectionFilter);
+		MockHttpServletRequest request = tester.getRequest();
+		for (String origin : origins)
+		{
+			request.addHeader("Origin", origin);
+		}
+		request.addParameter("resourceName", TestWebSocketResource.TEXT);
+		request.addParameter(WebRequest.PARAM_AJAX_BASE_URL, ".");
+	}
+
+}