Expose allowedOriginPatterns in SocketJS XML config

Closes gh-26108
This commit is contained in:
Rossen Stoyanchev
2020-11-18 21:20:38 +00:00
parent 8130bf505f
commit 684e695b08
8 changed files with 57 additions and 12 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 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.
@@ -32,6 +32,7 @@ import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.beans.factory.xml.BeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.lang.Nullable;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.springframework.web.socket.server.support.OriginHandshakeInterceptor;
@@ -85,7 +86,13 @@ class HandlersBeanDefinitionParser implements BeanDefinitionParser {
ManagedList<Object> interceptors = WebSocketNamespaceUtils.parseBeanSubElements(interceptElem, context);
String allowedOrigins = element.getAttribute("allowed-origins");
List<String> origins = Arrays.asList(StringUtils.tokenizeToStringArray(allowedOrigins, ","));
interceptors.add(new OriginHandshakeInterceptor(origins));
String allowedOriginPatterns = element.getAttribute("allowed-origin-patterns");
List<String> originPatterns = Arrays.asList(StringUtils.tokenizeToStringArray(allowedOriginPatterns, ","));
OriginHandshakeInterceptor interceptor = new OriginHandshakeInterceptor(origins);
if (!ObjectUtils.isEmpty(originPatterns)) {
interceptor.setAllowedOriginPatterns(originPatterns);
}
interceptors.add(interceptor);
strategy = new WebSocketHandlerMappingStrategy(handler, interceptors);
}

View File

@@ -60,6 +60,7 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.MimeTypeUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.springframework.web.socket.WebSocketHandler;
@@ -358,7 +359,13 @@ class MessageBrokerBeanDefinitionParser implements BeanDefinitionParser {
ManagedList<Object> interceptors = WebSocketNamespaceUtils.parseBeanSubElements(interceptElem, ctx);
String allowedOrigins = element.getAttribute("allowed-origins");
List<String> origins = Arrays.asList(StringUtils.tokenizeToStringArray(allowedOrigins, ","));
interceptors.add(new OriginHandshakeInterceptor(origins));
String allowedOriginPatterns = element.getAttribute("allowed-origin-patterns");
List<String> originPatterns = Arrays.asList(StringUtils.tokenizeToStringArray(allowedOriginPatterns, ","));
OriginHandshakeInterceptor interceptor = new OriginHandshakeInterceptor(origins);
if (!ObjectUtils.isEmpty(originPatterns)) {
interceptor.setAllowedOriginPatterns(originPatterns);
}
interceptors.add(interceptor);
ConstructorArgumentValues cargs = new ConstructorArgumentValues();
cargs.addIndexedArgumentValue(0, subProtoHandler);
cargs.addIndexedArgumentValue(1, handler);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2020 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.
@@ -105,11 +105,18 @@ abstract class WebSocketNamespaceUtils {
Element interceptElem = DomUtils.getChildElementByTagName(element, "handshake-interceptors");
ManagedList<Object> interceptors = WebSocketNamespaceUtils.parseBeanSubElements(interceptElem, context);
String allowedOrigins = element.getAttribute("allowed-origins");
List<String> origins = Arrays.asList(StringUtils.tokenizeToStringArray(allowedOrigins, ","));
sockJsServiceDef.getPropertyValues().add("allowedOrigins", origins);
String allowedOriginPatterns = element.getAttribute("allowed-origin-patterns");
List<String> originPatterns = Arrays.asList(StringUtils.tokenizeToStringArray(allowedOriginPatterns, ","));
sockJsServiceDef.getPropertyValues().add("allowedOriginPatterns", originPatterns);
RootBeanDefinition originHandshakeInterceptor = new RootBeanDefinition(OriginHandshakeInterceptor.class);
originHandshakeInterceptor.getPropertyValues().add("allowedOrigins", origins);
originHandshakeInterceptor.getPropertyValues().add("allowedOriginPatterns", originPatterns);
interceptors.add(originHandshakeInterceptor);
sockJsServiceDef.getPropertyValues().add("handshakeInterceptors", interceptors);

View File

@@ -541,6 +541,16 @@
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="allowed-origin-patterns" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Alternative to allowed-origins that supports origins declared via patterns,
e.g. "*.domain1.com".
By default this is not set.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
@@ -739,6 +749,16 @@
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="allowed-origin-patterns" type="xsd:string">
<xsd:annotation>
<xsd:documentation><![CDATA[
Alternative to allowed-origins that supports origins declared via patterns,
e.g. "*.domain1.com".
By default this is not set.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="stomp-error-handler" minOccurs="0">

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2019 the original author or authors.
* Copyright 2002-2020 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.
@@ -226,8 +226,8 @@ public class HandlersBeanDefinitionParserTests {
List<HandshakeInterceptor> interceptors = transportService.getHandshakeInterceptors();
assertThat(interceptors).extracting("class").containsExactly(OriginHandshakeInterceptor.class);
assertThat(transportService.shouldSuppressCors()).isTrue();
assertThat(transportService.getAllowedOrigins().contains("https://mydomain1.example")).isTrue();
assertThat(transportService.getAllowedOrigins().contains("https://mydomain2.example")).isTrue();
assertThat(transportService.getAllowedOrigins()).containsExactly("https://mydomain1.example", "https://mydomain2.example");
assertThat(transportService.getAllowedOriginPatterns()).containsExactly("https://*.mydomain.example");
}

View File

@@ -181,8 +181,8 @@ public class MessageBrokerBeanDefinitionParserTests {
interceptors = defaultSockJsService.getHandshakeInterceptors();
assertThat(interceptors).extracting("class").containsExactly(FooTestInterceptor.class,
BarTestInterceptor.class, OriginHandshakeInterceptor.class);
assertThat(defaultSockJsService.getAllowedOrigins().contains("https://mydomain3.com")).isTrue();
assertThat(defaultSockJsService.getAllowedOrigins().contains("https://mydomain4.com")).isTrue();
assertThat(defaultSockJsService.getAllowedOrigins()).containsExactly("https://mydomain3.com", "https://mydomain4.com");
assertThat(defaultSockJsService.getAllowedOriginPatterns()).containsExactly("https://*.mydomain.com");
SimpUserRegistry userRegistry = this.appContext.getBean(SimpUserRegistry.class);
assertThat(userRegistry).isNotNull();

View File

@@ -17,7 +17,9 @@
</websocket:decorator-factories>
</websocket:transport>
<websocket:stomp-endpoint path=" /foo,/bar" allowed-origins="https://mydomain1.example,https://mydomain2.example">
<websocket:stomp-endpoint path=" /foo,/bar"
allowed-origins="https://mydomain1.example,https://mydomain2.example"
allowed-origin-patterns="https://*.mydomain.com">
<websocket:handshake-handler ref="myHandler"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.config.FooTestInterceptor"/>
@@ -25,7 +27,9 @@
</websocket:handshake-interceptors>
</websocket:stomp-endpoint>
<websocket:stomp-endpoint path="/test,/sockjs" allowed-origins="https://mydomain3.com,https://mydomain4.com">
<websocket:stomp-endpoint path="/test,/sockjs"
allowed-origins="https://mydomain3.com,https://mydomain4.com"
allowed-origin-patterns="https://*.mydomain.com">
<websocket:handshake-handler ref="myHandler"/>
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.config.FooTestInterceptor"/>

View File

@@ -5,7 +5,7 @@
http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/websocket https://www.springframework.org/schema/websocket/spring-websocket.xsd">
<websocket:handlers allowed-origins="https://mydomain1.example, https://mydomain2.example">
<websocket:handlers allowed-origins="https://mydomain1.example, https://mydomain2.example" allowed-origin-patterns="https://*.mydomain.example">
<websocket:mapping path="/test" handler="testHandler"/>
<websocket:sockjs name="testSockJsService" scheduler="testTaskScheduler" websocket-enabled="false"
session-cookie-needed="false" stream-bytes-limit="2048" disconnect-delay="256"