Skip to content

Commit 8130bf5

Browse files
committed
Apply allowedOriginPatterns in SockJsService
See gh-26108
1 parent 9beca06 commit 8130bf5

File tree

3 files changed

+37
-32
lines changed

3 files changed

+37
-32
lines changed

spring-websocket/src/main/java/org/springframework/web/socket/sockjs/support/AbstractSockJsService.java

Lines changed: 32 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@
2525
import java.util.LinkedHashSet;
2626
import java.util.List;
2727
import java.util.Random;
28-
import java.util.Set;
2928
import java.util.concurrent.TimeUnit;
3029

3130
import javax.servlet.http.HttpServletRequest;
@@ -97,9 +96,7 @@ public abstract class AbstractSockJsService implements SockJsService, CorsConfig
9796

9897
private boolean suppressCors = false;
9998

100-
protected final Set<String> allowedOrigins = new LinkedHashSet<>();
101-
102-
protected final Set<String> allowedOriginPatterns = new LinkedHashSet<>();
99+
protected final CorsConfiguration corsConfiguration;
103100

104101
private final SockJsRequestHandler infoHandler = new InfoHandler();
105102

@@ -109,6 +106,18 @@ public abstract class AbstractSockJsService implements SockJsService, CorsConfig
109106
public AbstractSockJsService(TaskScheduler scheduler) {
110107
Assert.notNull(scheduler, "TaskScheduler must not be null");
111108
this.taskScheduler = scheduler;
109+
this.corsConfiguration = initCorsConfiguration();
110+
}
111+
112+
private static CorsConfiguration initCorsConfiguration() {
113+
CorsConfiguration config = new CorsConfiguration();
114+
config.addAllowedMethod("*");
115+
config.setAllowedOrigins(Collections.emptyList());
116+
config.setAllowedOriginPatterns(Collections.emptyList());
117+
config.setAllowCredentials(true);
118+
config.setMaxAge(ONE_YEAR);
119+
config.addAllowedHeader("*");
120+
return config;
112121
}
113122

114123

@@ -317,10 +326,18 @@ public boolean shouldSuppressCors() {
317326
*/
318327
public void setAllowedOrigins(Collection<String> allowedOrigins) {
319328
Assert.notNull(allowedOrigins, "Allowed origins Collection must not be null");
320-
this.allowedOrigins.clear();
321-
this.allowedOrigins.addAll(allowedOrigins);
329+
this.corsConfiguration.setAllowedOrigins(new ArrayList<>(allowedOrigins));
322330
}
323331

332+
/**
333+
* Return configure allowed {@code Origin} header values.
334+
* @since 4.1.2
335+
* @see #setAllowedOrigins
336+
*/
337+
@SuppressWarnings("ConstantConditions")
338+
public Collection<String> getAllowedOrigins() {
339+
return this.corsConfiguration.getAllowedOrigins();
340+
}
324341
/**
325342
* A variant of {@link #setAllowedOrigins(Collection)} that accepts flexible
326343
* domain patterns, e.g. {@code "https://*.domain1.com"}. Furthermore it
@@ -331,26 +348,17 @@ public void setAllowedOrigins(Collection<String> allowedOrigins) {
331348
*/
332349
public void setAllowedOriginPatterns(Collection<String> allowedOriginPatterns) {
333350
Assert.notNull(allowedOriginPatterns, "Allowed origin patterns Collection must not be null");
334-
this.allowedOriginPatterns.clear();
335-
this.allowedOriginPatterns.addAll(allowedOriginPatterns);
336-
}
337-
338-
/**
339-
* Return configure allowed {@code Origin} header values.
340-
* @since 4.1.2
341-
* @see #setAllowedOrigins
342-
*/
343-
public Collection<String> getAllowedOrigins() {
344-
return Collections.unmodifiableSet(this.allowedOrigins);
351+
this.corsConfiguration.setAllowedOriginPatterns(new ArrayList<>(allowedOriginPatterns));
345352
}
346353

347354
/**
348-
* Return configure allowed {@code Origin} pattern header values.
355+
* Return {@link #setAllowedOriginPatterns(Collection) configured} origin patterns.
349356
* @since 5.3.2
350357
* @see #setAllowedOriginPatterns
351358
*/
359+
@SuppressWarnings("ConstantConditions")
352360
public Collection<String> getAllowedOriginPatterns() {
353-
return Collections.unmodifiableSet(this.allowedOriginPatterns);
361+
return this.corsConfiguration.getAllowedOriginPatterns();
354362
}
355363

356364

@@ -396,15 +404,16 @@ else if (sockJsPath.equals("/info")) {
396404
}
397405

398406
else if (sockJsPath.matches("/iframe[0-9-.a-z_]*.html")) {
399-
if (!this.allowedOrigins.isEmpty() && !this.allowedOrigins.contains("*")) {
407+
if (!getAllowedOrigins().isEmpty() && !getAllowedOrigins().contains("*") ||
408+
!getAllowedOriginPatterns().isEmpty()) {
400409
if (requestInfo != null) {
401410
logger.debug("Iframe support is disabled when an origin check is required. " +
402411
"Ignoring transport request: " + requestInfo);
403412
}
404413
response.setStatusCode(HttpStatus.NOT_FOUND);
405414
return;
406415
}
407-
if (this.allowedOrigins.isEmpty()) {
416+
if (getAllowedOrigins().isEmpty()) {
408417
response.getHeaders().add(XFRAME_OPTIONS_HEADER, "SAMEORIGIN");
409418
}
410419
if (requestInfo != null) {
@@ -506,7 +515,7 @@ protected boolean checkOrigin(ServerHttpRequest request, ServerHttpResponse resp
506515
return true;
507516
}
508517

509-
if (!WebUtils.isValidOrigin(request, this.allowedOrigins)) {
518+
if (this.corsConfiguration.checkOrigin(request.getHeaders().getOrigin()) == null) {
510519
if (logger.isWarnEnabled()) {
511520
logger.warn("Origin header value '" + request.getHeaders().getOrigin() + "' not allowed.");
512521
}
@@ -521,14 +530,7 @@ protected boolean checkOrigin(ServerHttpRequest request, ServerHttpResponse resp
521530
@Nullable
522531
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
523532
if (!this.suppressCors && (request.getHeader(HttpHeaders.ORIGIN) != null)) {
524-
CorsConfiguration config = new CorsConfiguration();
525-
config.setAllowedOrigins(new ArrayList<>(this.allowedOrigins));
526-
config.setAllowedOriginPatterns(new ArrayList<>(this.allowedOriginPatterns));
527-
config.addAllowedMethod("*");
528-
config.setAllowCredentials(true);
529-
config.setMaxAge(ONE_YEAR);
530-
config.addAllowedHeader("*");
531-
return config;
533+
return this.corsConfiguration;
532534
}
533535
return null;
534536
}

spring-websocket/src/main/java/org/springframework/web/socket/sockjs/transport/TransportHandlingSockJsService.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,8 @@ protected boolean validateRequest(String serverId, String sessionId, String tran
344344
return false;
345345
}
346346

347-
if (!this.allowedOrigins.contains("*")) {
347+
if (!getAllowedOrigins().isEmpty() && !getAllowedOrigins().contains("*") ||
348+
!getAllowedOriginPatterns().isEmpty()) {
348349
TransportType transportType = TransportType.fromValue(transport);
349350
if (transportType == null || !transportType.supportsOrigin()) {
350351
if (logger.isWarnEnabled()) {

spring-websocket/src/test/java/org/springframework/web/socket/sockjs/support/SockJsServiceTests.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,18 +215,20 @@ public void handleInfoOptionsWithForbiddenOrigin() {
215215
@Test // SPR-12283
216216
public void handleInfoOptionsWithOriginAndCorsHeadersDisabled() {
217217
this.servletRequest.addHeader(HttpHeaders.ORIGIN, "https://mydomain2.example");
218-
this.service.setAllowedOrigins(Collections.singletonList("*"));
218+
this.service.setAllowedOriginPatterns(Collections.singletonList("*"));
219219
this.service.setSuppressCors(true);
220220

221221
this.servletRequest.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_HEADERS, "Last-Modified");
222222
resetResponseAndHandleRequest("OPTIONS", "/echo/info", HttpStatus.NO_CONTENT);
223223
assertThat(this.service.getCorsConfiguration(this.servletRequest)).isNull();
224224

225225
this.service.setAllowedOrigins(Collections.singletonList("https://mydomain1.example"));
226+
this.service.setAllowedOriginPatterns(Collections.emptyList());
226227
resetResponseAndHandleRequest("OPTIONS", "/echo/info", HttpStatus.FORBIDDEN);
227228
assertThat(this.service.getCorsConfiguration(this.servletRequest)).isNull();
228229

229230
this.service.setAllowedOrigins(Arrays.asList("https://mydomain1.example", "https://mydomain2.example", "http://mydomain3.example"));
231+
this.service.setAllowedOriginPatterns(Collections.emptyList());
230232
resetResponseAndHandleRequest("OPTIONS", "/echo/info", HttpStatus.NO_CONTENT);
231233
assertThat(this.service.getCorsConfiguration(this.servletRequest)).isNull();
232234
}

0 commit comments

Comments
 (0)