Support for placeholders in @CrossOrigin attributes

Issue: SPR-14010
This commit is contained in:
Juergen Hoeller
2016-03-11 15:04:16 +01:00
parent b4de66ff9a
commit 8852a5e178
2 changed files with 73 additions and 37 deletions

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.
@@ -22,6 +22,7 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Properties;
import org.junit.Before;
import org.junit.Rule;
@@ -29,8 +30,10 @@ import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.env.PropertiesPropertySource;
import org.springframework.http.HttpHeaders;
import org.springframework.mock.web.test.MockHttpServletRequest;
import org.springframework.stereotype.Controller;
@@ -72,9 +75,15 @@ public class CrossOriginTests {
@Before
public void setUp() {
StaticWebApplicationContext wac = new StaticWebApplicationContext();
Properties props = new Properties();
props.setProperty("myOrigin", "http://example.com");
wac.getEnvironment().getPropertySources().addFirst(new PropertiesPropertySource("ps", props));
wac.registerSingleton("ppc", PropertySourcesPlaceholderConfigurer.class);
wac.refresh();
this.handlerMapping.setRemoveSemicolonContent(false);
this.handlerMapping.setApplicationContext(new StaticWebApplicationContext());
this.handlerMapping.afterPropertiesSet();
wac.getAutowireCapableBeanFactory().initializeBean(this.handlerMapping, "hm");
this.request.setMethod("GET");
this.request.addHeader(HttpHeaders.ORIGIN, "http://domain.com/");
@@ -112,10 +121,10 @@ public class CrossOriginTests {
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
CorsConfiguration config = getCorsConfiguration(chain, false);
assertNotNull(config);
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"*"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedOrigins().toArray());
assertTrue(config.getAllowCredentials());
assertArrayEquals(new String[]{"*"}, config.getAllowedHeaders().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedHeaders().toArray());
assertTrue(CollectionUtils.isEmpty(config.getExposedHeaders()));
assertEquals(new Long(1800), config.getMaxAge());
}
@@ -127,10 +136,10 @@ public class CrossOriginTests {
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
CorsConfiguration config = getCorsConfiguration(chain, false);
assertNotNull(config);
assertArrayEquals(new String[]{"DELETE"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"http://site1.com", "http://site2.com"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[]{"header1", "header2"}, config.getAllowedHeaders().toArray());
assertArrayEquals(new String[]{"header3", "header4"}, config.getExposedHeaders().toArray());
assertArrayEquals(new String[] {"DELETE"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"http://site1.com", "http://site2.com"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"header1", "header2"}, config.getAllowedHeaders().toArray());
assertArrayEquals(new String[] {"header3", "header4"}, config.getExposedHeaders().toArray());
assertEquals(new Long(123), config.getMaxAge());
assertFalse(config.getAllowCredentials());
}
@@ -146,6 +155,17 @@ public class CrossOriginTests {
assertTrue(config.getAllowCredentials());
}
@Test
public void customOriginDefinedViaPlaceholder() throws Exception {
this.handlerMapping.registerHandler(new MethodLevelController());
this.request.setRequestURI("/someOrigin");
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
CorsConfiguration config = getCorsConfiguration(chain, false);
assertNotNull(config);
assertEquals(Arrays.asList("http://example.com"), config.getAllowedOrigins());
assertTrue(config.getAllowCredentials());
}
@Test
public void bogusAllowCredentialsValue() throws Exception {
exception.expect(IllegalStateException.class);
@@ -162,24 +182,24 @@ public class CrossOriginTests {
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
CorsConfiguration config = getCorsConfiguration(chain, false);
assertNotNull(config);
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"*"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedOrigins().toArray());
assertFalse(config.getAllowCredentials());
this.request.setRequestURI("/bar");
chain = this.handlerMapping.getHandler(request);
config = getCorsConfiguration(chain, false);
assertNotNull(config);
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"*"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedOrigins().toArray());
assertFalse(config.getAllowCredentials());
this.request.setRequestURI("/baz");
chain = this.handlerMapping.getHandler(request);
config = getCorsConfiguration(chain, false);
assertNotNull(config);
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"*"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedOrigins().toArray());
assertTrue(config.getAllowCredentials());
}
@@ -191,8 +211,8 @@ public class CrossOriginTests {
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
CorsConfiguration config = getCorsConfiguration(chain, false);
assertNotNull(config);
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"http://foo.com"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"http://foo.com"}, config.getAllowedOrigins().toArray());
assertTrue(config.getAllowCredentials());
}
@@ -204,8 +224,8 @@ public class CrossOriginTests {
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
CorsConfiguration config = getCorsConfiguration(chain, false);
assertNotNull(config);
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"http://foo.com"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"http://foo.com"}, config.getAllowedOrigins().toArray());
assertTrue(config.getAllowCredentials());
}
@@ -218,10 +238,10 @@ public class CrossOriginTests {
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
CorsConfiguration config = getCorsConfiguration(chain, true);
assertNotNull(config);
assertArrayEquals(new String[]{"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"*"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"GET"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedOrigins().toArray());
assertTrue(config.getAllowCredentials());
assertArrayEquals(new String[]{"*"}, config.getAllowedHeaders().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedHeaders().toArray());
assertTrue(CollectionUtils.isEmpty(config.getExposedHeaders()));
assertEquals(new Long(1800), config.getMaxAge());
}
@@ -236,9 +256,9 @@ public class CrossOriginTests {
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
CorsConfiguration config = getCorsConfiguration(chain, true);
assertNotNull(config);
assertArrayEquals(new String[]{"*"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"*"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[]{"*"}, config.getAllowedHeaders().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedHeaders().toArray());
assertTrue(config.getAllowCredentials());
assertTrue(CollectionUtils.isEmpty(config.getExposedHeaders()));
assertNull(config.getMaxAge());
@@ -253,9 +273,9 @@ public class CrossOriginTests {
HandlerExecutionChain chain = this.handlerMapping.getHandler(request);
CorsConfiguration config = getCorsConfiguration(chain, true);
assertNotNull(config);
assertArrayEquals(new String[]{"*"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[]{"*"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[]{"*"}, config.getAllowedHeaders().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedMethods().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedOrigins().toArray());
assertArrayEquals(new String[] {"*"}, config.getAllowedHeaders().toArray());
assertTrue(config.getAllowCredentials());
assertTrue(CollectionUtils.isEmpty(config.getExposedHeaders()));
assertNull(config.getMaxAge());
@@ -343,8 +363,14 @@ public class CrossOriginTests {
@RequestMapping("/customOrigin")
public void customOriginDefinedViaValueAttribute() {
}
@CrossOrigin("${myOrigin}")
@RequestMapping("/someOrigin")
public void customOriginDefinedViaPlaceholder() {
}
}
@Controller
private static class MethodLevelControllerWithBogusAllowCredentialsValue {
@@ -354,6 +380,7 @@ public class CrossOriginTests {
}
}
@Controller
@CrossOrigin(allowCredentials = "false")
private static class ClassLevelController {
@@ -374,14 +401,18 @@ public class CrossOriginTests {
}
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@CrossOrigin
private @interface ComposedCrossOrigin {
String[] origins() default {};
String allowCredentials() default "";
}
@Controller
@ComposedCrossOrigin(origins = "http://foo.com", allowCredentials = "true")
private static class ClassLevelMappingWithComposedAnnotation {
@@ -401,6 +432,7 @@ public class CrossOriginTests {
}
}
private static class TestRequestMappingInfoHandlerMapping extends RequestMappingHandlerMapping {
public void registerHandler(Object handler) {