Check SockJS session type

This commits adds a validation check whether the SockJS session type
matches the transport type and rejects requests for which they
don't match.

Issue: SPR-14867
This commit is contained in:
Rossen Stoyanchev
2016-11-03 09:35:30 +02:00
parent 8705df502d
commit 87e01513fd
10 changed files with 65 additions and 4 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2013 the original author or authors.
* Copyright 2002-2016 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.
@@ -43,6 +43,14 @@ public interface TransportHandler {
*/
TransportType getTransportType();
/**
* Whether the type of the given session matches the transport type of this
* {@code TransportHandler} where session id and the transport type are
* extracted from the SockJS URL.
* @since 4.3.3
*/
boolean checkSessionType(SockJsSession session);
/**
* Handle the given request and delegate messages to the provided
* {@link WebSocketHandler}.

View File

@@ -291,6 +291,11 @@ public class TransportHandlingSockJsService extends AbstractSockJsService implem
return;
}
}
if (!transportHandler.checkSessionType(session)) {
logger.debug("Session type does not match the transport type for the request.");
response.setStatusCode(HttpStatus.NOT_FOUND);
return;
}
}
if (transportType.sendsNoCacheInstruction()) {
@@ -303,7 +308,10 @@ public class TransportHandlingSockJsService extends AbstractSockJsService implem
}
}
transportHandler.handleRequest(request, response, handler, session);
chain.applyAfterHandshake(request, response, null);
}
catch (SockJsException ex) {

View File

@@ -99,4 +99,9 @@ public abstract class AbstractHttpReceivingTransportHandler extends AbstractTran
protected abstract HttpStatus getResponseStatus();
@Override
public boolean checkSessionType(SockJsSession session) {
return session instanceof AbstractHttpSockJsSession;
}
}

View File

@@ -25,7 +25,9 @@ import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.sockjs.frame.DefaultSockJsFrameFormat;
import org.springframework.web.socket.sockjs.frame.SockJsFrameFormat;
import org.springframework.web.socket.sockjs.transport.SockJsServiceConfig;
import org.springframework.web.socket.sockjs.transport.SockJsSession;
import org.springframework.web.socket.sockjs.transport.TransportType;
import org.springframework.web.socket.sockjs.transport.session.PollingSockJsSession;
import org.springframework.web.socket.sockjs.transport.session.StreamingSockJsSession;
/**
@@ -47,6 +49,11 @@ public class EventSourceTransportHandler extends AbstractHttpSendingTransportHan
return new MediaType("text", "event-stream", StandardCharsets.UTF_8);
}
@Override
public boolean checkSessionType(SockJsSession session) {
return session instanceof EventSourceStreamingSockJsSession;
}
@Override
public StreamingSockJsSession createSession(
String sessionId, WebSocketHandler handler, Map<String, Object> attributes) {

View File

@@ -32,9 +32,11 @@ import org.springframework.web.socket.sockjs.SockJsTransportFailureException;
import org.springframework.web.socket.sockjs.frame.DefaultSockJsFrameFormat;
import org.springframework.web.socket.sockjs.frame.SockJsFrameFormat;
import org.springframework.web.socket.sockjs.transport.SockJsServiceConfig;
import org.springframework.web.socket.sockjs.transport.SockJsSession;
import org.springframework.web.socket.sockjs.transport.TransportHandler;
import org.springframework.web.socket.sockjs.transport.TransportType;
import org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession;
import org.springframework.web.socket.sockjs.transport.session.PollingSockJsSession;
import org.springframework.web.socket.sockjs.transport.session.StreamingSockJsSession;
import org.springframework.web.util.JavaScriptUtils;
@@ -88,6 +90,11 @@ public class HtmlFileTransportHandler extends AbstractHttpSendingTransportHandle
return new MediaType("text", "html", StandardCharsets.UTF_8);
}
@Override
public boolean checkSessionType(SockJsSession session) {
return session instanceof HtmlFileStreamingSockJsSession;
}
@Override
public StreamingSockJsSession createSession(
String sessionId, WebSocketHandler handler, Map<String, Object> attributes) {

View File

@@ -30,6 +30,7 @@ import org.springframework.web.socket.sockjs.SockJsException;
import org.springframework.web.socket.sockjs.SockJsTransportFailureException;
import org.springframework.web.socket.sockjs.frame.DefaultSockJsFrameFormat;
import org.springframework.web.socket.sockjs.frame.SockJsFrameFormat;
import org.springframework.web.socket.sockjs.transport.SockJsSession;
import org.springframework.web.socket.sockjs.transport.TransportType;
import org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession;
import org.springframework.web.socket.sockjs.transport.session.PollingSockJsSession;
@@ -53,6 +54,11 @@ public class JsonpPollingTransportHandler extends AbstractHttpSendingTransportHa
return new MediaType("application", "javascript", StandardCharsets.UTF_8);
}
@Override
public boolean checkSessionType(SockJsSession session) {
return session instanceof PollingSockJsSession;
}
@Override
public PollingSockJsSession createSession(
String sessionId, WebSocketHandler handler, Map<String, Object> attributes) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -103,6 +103,11 @@ public class WebSocketTransportHandler extends AbstractTransportHandler
}
}
@Override
public boolean checkSessionType(SockJsSession session) {
return session instanceof WebSocketServerSockJsSession;
}
@Override
public AbstractSockJsSession createSession(String id, WebSocketHandler handler, Map<String, Object> attrs) {
return new WebSocketServerSockJsSession(id, getServiceConfig(), handler, attrs);

View File

@@ -24,8 +24,10 @@ import org.springframework.http.server.ServerHttpRequest;
import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.sockjs.frame.DefaultSockJsFrameFormat;
import org.springframework.web.socket.sockjs.frame.SockJsFrameFormat;
import org.springframework.web.socket.sockjs.transport.SockJsSession;
import org.springframework.web.socket.sockjs.transport.TransportHandler;
import org.springframework.web.socket.sockjs.transport.TransportType;
import org.springframework.web.socket.sockjs.transport.session.AbstractHttpSockJsSession;
import org.springframework.web.socket.sockjs.transport.session.PollingSockJsSession;
/**
@@ -51,6 +53,11 @@ public class XhrPollingTransportHandler extends AbstractHttpSendingTransportHand
return new DefaultSockJsFrameFormat("%s\n");
}
@Override
public boolean checkSessionType(SockJsSession session) {
return session instanceof PollingSockJsSession;
}
@Override
public PollingSockJsSession createSession(
String sessionId, WebSocketHandler handler, Map<String, Object> attributes) {

View File

@@ -25,8 +25,10 @@ import org.springframework.web.socket.WebSocketHandler;
import org.springframework.web.socket.sockjs.frame.DefaultSockJsFrameFormat;
import org.springframework.web.socket.sockjs.frame.SockJsFrameFormat;
import org.springframework.web.socket.sockjs.transport.SockJsServiceConfig;
import org.springframework.web.socket.sockjs.transport.SockJsSession;
import org.springframework.web.socket.sockjs.transport.TransportHandler;
import org.springframework.web.socket.sockjs.transport.TransportType;
import org.springframework.web.socket.sockjs.transport.session.PollingSockJsSession;
import org.springframework.web.socket.sockjs.transport.session.StreamingSockJsSession;
/**
@@ -57,6 +59,11 @@ public class XhrStreamingTransportHandler extends AbstractHttpSendingTransportHa
return new MediaType("application", "javascript", StandardCharsets.UTF_8);
}
@Override
public boolean checkSessionType(SockJsSession session) {
return session instanceof XhrStreamingSockJsSession;
}
@Override
public StreamingSockJsSession createSession(
String sessionId, WebSocketHandler handler, Map<String, Object> attributes) {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2016 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.
@@ -44,7 +44,7 @@ import static org.junit.Assert.*;
import static org.mockito.BDDMockito.*;
/**
* Test fixture for {@link org.springframework.web.socket.sockjs.transport.handler.DefaultSockJsService}.
* Test fixture for {@link DefaultSockJsService}.
*
* @author Rossen Stoyanchev
* @author Sebastien Deleuze
@@ -239,6 +239,7 @@ public class DefaultSockJsServiceTests extends AbstractHttpRequestTests {
resetResponse();
sockJsPath = sessionUrlPrefix + "xhr_send";
setRequest("POST", sockJsPrefix + sockJsPath);
given(this.xhrSendHandler.checkSessionType(this.session)).willReturn(true);
this.service.handleRequest(this.request, this.response, sockJsPath, this.wsHandler);
assertEquals(200, this.servletResponse.getStatus()); // session exists