2
0
Эх сурвалжийг харах

HttpCorsConfigTests groovy->java

Issue: gh-4939
Josh Cummings 7 жил өмнө
parent
commit
428b0e45aa

+ 0 - 171
config/src/test/groovy/org/springframework/security/config/http/HttpCorsConfigTests.groovy

@@ -1,171 +0,0 @@
-/*
- * 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. 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.springframework.security.config.http
-
-import org.springframework.beans.factory.BeanCreationException
-
-import javax.servlet.http.HttpServletResponse
-
-import org.springframework.http.*
-import org.springframework.mock.web.*
-import org.springframework.security.web.authentication.Http403ForbiddenEntryPoint
-import org.springframework.web.bind.annotation.*
-import org.springframework.web.filter.CorsFilter
-import org.springframework.web.cors.CorsConfiguration
-import org.springframework.web.cors.UrlBasedCorsConfigurationSource
-
-/**
- *
- * @author Rob Winch
- * @author Tim Ysewyn
- */
-class HttpCorsConfigTests extends AbstractHttpConfigTests {
-	MockHttpServletRequest request
-	MockHttpServletResponse response
-	MockFilterChain chain
-
-	def setup() {
-		request = new MockHttpServletRequest(method:"GET")
-		response = new MockHttpServletResponse()
-		chain = new MockFilterChain()
-	}
-
-	def "No MVC throws meaningful error"() {
-		when:
-		xml.http('entry-point-ref' : 'ep') {
-			'cors'()
-			'intercept-url'(pattern:'/**', access: 'authenticated')
-		}
-		bean('ep', Http403ForbiddenEntryPoint)
-		createAppContext()
-		then:
-		BeanCreationException success = thrown()
-		success.message.contains("Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext")
-	}
-
-	def "HandlerMappingIntrospector explicit"() {
-		setup:
-		xml.http('entry-point-ref' : 'ep') {
-			'cors'()
-			'intercept-url'(pattern:'/**', access: 'authenticated')
-		}
-		bean('ep', Http403ForbiddenEntryPoint)
-		bean('controller', CorsController)
-		xml.'mvc:annotation-driven'()
-		createAppContext()
-		when:
-		addCors()
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: 'Ensure we a CORS response w/ Spring Security headers too'
-		responseHeaders['Access-Control-Allow-Origin']
-		responseHeaders['X-Content-Type-Options']
-		when:
-		setup()
-		addCors(true)
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: 'Ensure we a CORS response w/ Spring Security headers too'
-		responseHeaders['Access-Control-Allow-Origin']
-		responseHeaders['X-Content-Type-Options']
-		response.status == HttpServletResponse.SC_OK
-	}
-
-	def "CorsConfigurationSource"() {
-		setup:
-		xml.http('entry-point-ref' : 'ep') {
-			'cors'('configuration-source-ref':'ccs')
-			'intercept-url'(pattern:'/**', access: 'authenticated')
-		}
-		bean('ep', Http403ForbiddenEntryPoint)
-		bean('ccs', MyCorsConfigurationSource)
-		createAppContext()
-		when:
-		addCors()
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: 'Ensure we a CORS response w/ Spring Security headers too'
-		responseHeaders['Access-Control-Allow-Origin']
-		responseHeaders['X-Content-Type-Options']
-		when:
-		setup()
-		addCors(true)
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: 'Ensure we a CORS response w/ Spring Security headers too'
-		responseHeaders['Access-Control-Allow-Origin']
-		responseHeaders['X-Content-Type-Options']
-		response.status == HttpServletResponse.SC_OK
-	}
-
-	def "CorsFilter"() {
-		setup:
-		xml.http('entry-point-ref' : 'ep') {
-			'cors'('ref' : 'cf')
-			'intercept-url'(pattern:'/**', access: 'authenticated')
-		}
-		xml.'b:bean'(id: 'cf', 'class': CorsFilter.name) {
-			'b:constructor-arg'(ref: 'ccs')
-		}
-		bean('ep', Http403ForbiddenEntryPoint)
-		bean('ccs', MyCorsConfigurationSource)
-		createAppContext()
-		when:
-		addCors()
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: 'Ensure we a CORS response w/ Spring Security headers too'
-		responseHeaders['Access-Control-Allow-Origin']
-		responseHeaders['X-Content-Type-Options']
-		when:
-		setup()
-		addCors(true)
-		springSecurityFilterChain.doFilter(request,response,chain)
-		then: 'Ensure we a CORS response w/ Spring Security headers too'
-		responseHeaders['Access-Control-Allow-Origin']
-		responseHeaders['X-Content-Type-Options']
-		response.status == HttpServletResponse.SC_OK
-	}
-
-	def addCors(boolean isPreflight=false) {
-		request.addHeader(HttpHeaders.ORIGIN,"https://example.com")
-		if(!isPreflight) {
-			return
-		}
-		request.method = HttpMethod.OPTIONS.name()
-		request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name())
-	}
-
-	def getResponseHeaders() {
-		def headers = [:]
-		response.headerNames.each { name ->
-			headers.put(name, response.getHeaderValues(name).join(','))
-		}
-		return headers
-	}
-
-	@RestController
-	@CrossOrigin(methods = [
-		RequestMethod.GET, RequestMethod.POST
-	])
-	static class CorsController {
-		@RequestMapping("/")
-		String hello() {
-			"Hello"
-		}
-	}
-
-	static class MyCorsConfigurationSource extends UrlBasedCorsConfigurationSource {
-		MyCorsConfigurationSource() {
-			registerCorsConfiguration('/**', new CorsConfiguration(allowedOrigins : ['*'], allowedMethods : [
-				RequestMethod.GET.name(),
-				RequestMethod.POST.name()
-			]))
-		}
-	}
-}

+ 168 - 0
config/src/test/java/org/springframework/security/config/http/HttpCorsConfigTests.java

@@ -0,0 +1,168 @@
+/*
+ * Copyright 2002-2018 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.
+ * 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.springframework.security.config.http;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.springframework.beans.factory.BeanCreationException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpMethod;
+import org.springframework.security.config.test.SpringTestRule;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.ResultMatcher;
+import org.springframework.test.web.servlet.request.RequestPostProcessor;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.cors.CorsConfiguration;
+import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
+
+import java.util.Arrays;
+
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+/**
+ *
+ * @author Rob Winch
+ * @author Tim Ysewyn
+ * @author Josh Cummings
+ */
+public class HttpCorsConfigTests {
+
+	private static final String CONFIG_LOCATION_PREFIX =
+			"classpath:org/springframework/security/config/http/HttpCorsConfigTests";
+
+	@Rule
+	public final SpringTestRule spring = new SpringTestRule();
+
+	@Autowired
+	MockMvc mvc;
+
+	@Test
+	public void autowireWhenMissingMvcThenGivesInformativeError() {
+		assertThatThrownBy(() ->
+				this.spring.configLocations(this.xml("RequiresMvc")).autowire())
+			.isInstanceOf(BeanCreationException.class)
+			.hasMessageContaining("Please ensure Spring Security & Spring MVC are configured in a shared ApplicationContext");
+	}
+
+	@Test
+	public void getWhenUsingCorsThenDoesSpringSecurityCorsHandshake()
+		throws Exception {
+
+		this.spring.configLocations(this.xml("WithCors")).autowire();
+
+		this.mvc.perform(get("/").with(this.approved()))
+				.andExpect(corsResponseHeaders())
+				.andExpect((status().isIAmATeapot()));
+
+		this.mvc.perform(options("/").with(this.preflight()))
+				.andExpect(corsResponseHeaders())
+				.andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenUsingCustomCorsConfigurationSourceThenDoesSpringSecurityCorsHandshake()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithCorsConfigurationSource")).autowire();
+
+		this.mvc.perform(get("/").with(this.approved()))
+				.andExpect(corsResponseHeaders())
+				.andExpect((status().isIAmATeapot()));
+
+		this.mvc.perform(options("/").with(this.preflight()))
+				.andExpect(corsResponseHeaders())
+				.andExpect(status().isOk());
+	}
+
+	@Test
+	public void getWhenUsingCustomCorsFilterThenDoesSPringSecurityCorsHandshake()
+			throws Exception {
+
+		this.spring.configLocations(this.xml("WithCorsFilter")).autowire();
+
+		this.mvc.perform(get("/").with(this.approved()))
+				.andExpect(corsResponseHeaders())
+				.andExpect((status().isIAmATeapot()));
+
+		this.mvc.perform(options("/").with(this.preflight()))
+				.andExpect(corsResponseHeaders())
+				.andExpect(status().isOk());
+	}
+
+	@RestController
+	@CrossOrigin(methods = {
+			RequestMethod.GET, RequestMethod.POST
+	})
+	static class CorsController {
+		@RequestMapping("/")
+		String hello() {
+			return "Hello";
+		}
+	}
+
+	static class MyCorsConfigurationSource extends UrlBasedCorsConfigurationSource {
+		MyCorsConfigurationSource() {
+			CorsConfiguration configuration = new CorsConfiguration();
+			configuration.setAllowedOrigins(Arrays.asList("*"));
+			configuration.setAllowedMethods(Arrays.asList(RequestMethod.GET.name(), RequestMethod.POST.name()));
+
+			super.registerCorsConfiguration(
+					"/**",
+					configuration);
+		}
+	}
+
+	private String xml(String configName) {
+		return CONFIG_LOCATION_PREFIX + "-" + configName + ".xml";
+	}
+
+	private RequestPostProcessor preflight() {
+		return cors(true);
+	}
+
+	private RequestPostProcessor approved() {
+		return cors(false);
+	}
+
+	private RequestPostProcessor cors(boolean preflight) {
+		return (request) -> {
+			request.addHeader(HttpHeaders.ORIGIN, "https://example.com");
+
+			if ( preflight ) {
+				request.setMethod(HttpMethod.OPTIONS.name());
+				request.addHeader(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, HttpMethod.POST.name());
+			}
+
+			return request;
+		};
+	}
+
+	private ResultMatcher corsResponseHeaders() {
+		return result -> {
+			header().exists("Access-Control-Allow-Origin").match(result);
+			header().exists("X-Content-Type-Options").match(result);
+		};
+	}
+
+}

+ 31 - 0
config/src/test/resources/org/springframework/security/config/http/HttpCorsConfigTests-RequiresMvc.xml

@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ 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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+
+	<http auto-config="true" use-expressions="false">
+		<cors/>
+	</http>
+</b:beans>

+ 45 - 0
config/src/test/resources/org/springframework/security/config/http/HttpCorsConfigTests-WithCors.xml

@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ 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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:mvc="http://www.springframework.org/schema/mvc"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd
+			http://www.springframework.org/schema/mvc
+			http://www.springframework.org/schema/mvc/spring-mvc.xsd">
+
+
+	<mvc:annotation-driven/>
+
+	<http entry-point-ref="ep">
+		<intercept-url pattern="/**" access="authenticated"/>
+		<cors/>
+	</http>
+
+	<b:bean name="ep" class="org.springframework.security.web.authentication.HttpStatusEntryPoint">
+		<b:constructor-arg value="I_AM_A_TEAPOT"/>
+	</b:bean>
+
+	<b:bean name="corsController" class="org.springframework.security.config.http.HttpCorsConfigTests.CorsController"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 39 - 0
config/src/test/resources/org/springframework/security/config/http/HttpCorsConfigTests-WithCorsConfigurationSource.xml

@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ 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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http entry-point-ref="ep">
+		<intercept-url pattern="/**" access="authenticated"/>
+		<cors configuration-source-ref="ccs"/>
+	</http>
+
+	<b:bean name="ep" class="org.springframework.security.web.authentication.HttpStatusEntryPoint">
+		<b:constructor-arg value="I_AM_A_TEAPOT"/>
+	</b:bean>
+	
+	<b:bean name="ccs" class="org.springframework.security.config.http.HttpCorsConfigTests.MyCorsConfigurationSource"/>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>

+ 43 - 0
config/src/test/resources/org/springframework/security/config/http/HttpCorsConfigTests-WithCorsFilter.xml

@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Copyright 2002-2018 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.
+  ~ 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.
+  -->
+
+<b:beans xmlns:b="http://www.springframework.org/schema/beans"
+		xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+		xmlns="http://www.springframework.org/schema/security"
+		xsi:schemaLocation="
+			http://www.springframework.org/schema/security
+			http://www.springframework.org/schema/security/spring-security.xsd
+			http://www.springframework.org/schema/beans
+			http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<http entry-point-ref="ep">
+		<intercept-url pattern="/**" access="authenticated"/>
+		<cors ref="cf"/>
+	</http>
+
+	<b:bean name="ep" class="org.springframework.security.web.authentication.HttpStatusEntryPoint">
+		<b:constructor-arg value="I_AM_A_TEAPOT"/>
+	</b:bean>
+
+	<b:bean name="cf" class="org.springframework.web.filter.CorsFilter">
+		<b:constructor-arg>
+			<b:bean class="org.springframework.security.config.http.HttpCorsConfigTests.MyCorsConfigurationSource"/>
+		</b:constructor-arg>
+	</b:bean>
+
+	<b:import resource="userservice.xml"/>
+</b:beans>