diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/filter/ErrorPageSecurityFilter.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/filter/ErrorPageSecurityFilter.java index 16bbc6bf93..77caff9889 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/filter/ErrorPageSecurityFilter.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/servlet/filter/ErrorPageSecurityFilter.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -35,6 +35,7 @@ import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; +import org.springframework.web.util.UrlPathHelper; /** * {@link Filter} that intercepts error dispatches to ensure authorized access to the @@ -48,12 +49,15 @@ public class ErrorPageSecurityFilter implements Filter { private static final WebInvocationPrivilegeEvaluator ALWAYS = new AlwaysAllowWebInvocationPrivilegeEvaluator(); + private final UrlPathHelper urlPathHelper = new UrlPathHelper(); + private final ApplicationContext context; private volatile WebInvocationPrivilegeEvaluator privilegeEvaluator; public ErrorPageSecurityFilter(ApplicationContext context) { this.context = context; + this.urlPathHelper.setAlwaysUseFullPath(true); } @Override @@ -81,7 +85,7 @@ public class ErrorPageSecurityFilter implements Filter { if (isUnauthenticated(authentication) && isNotAuthenticationError(errorCode)) { return true; } - return getPrivilegeEvaluator().isAllowed(request.getRequestURI(), authentication); + return getPrivilegeEvaluator().isAllowed(this.urlPathHelper.getPathWithinApplication(request), authentication); } private boolean isUnauthenticated(Authentication authentication) { diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/filter/ErrorPageSecurityFilterTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/filter/ErrorPageSecurityFilterTests.java index b44cf0e6bd..8a9da1cff4 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/filter/ErrorPageSecurityFilterTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/servlet/filter/ErrorPageSecurityFilterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -36,6 +36,7 @@ import org.springframework.security.web.access.WebInvocationPrivilegeEvaluator; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.ArgumentMatchers.eq; import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.willThrow; import static org.mockito.Mockito.mock; @@ -118,4 +119,30 @@ class ErrorPageSecurityFilterTests { verify(this.filterChain).doFilter(this.request, this.response); } + @Test + void whenThereIsAContextPathAndServletIsMappedToSlashContextPathIsNotPassedToEvaluator() throws Exception { + SecurityContext securityContext = mock(SecurityContext.class); + SecurityContextHolder.setContext(securityContext); + given(securityContext.getAuthentication()).willReturn(mock(Authentication.class)); + this.request.setRequestURI("/example/error"); + this.request.setContextPath("/example"); + // Servlet mapped to / + this.request.setServletPath("/error"); + this.securityFilter.doFilter(this.request, this.response, this.filterChain); + verify(this.privilegeEvaluator).isAllowed(eq("/error"), any()); + } + + @Test + void whenThereIsAContextPathAndServletIsMappedToWildcardPathCorrectPathIsPassedToEvaluator() throws Exception { + SecurityContext securityContext = mock(SecurityContext.class); + SecurityContextHolder.setContext(securityContext); + given(securityContext.getAuthentication()).willReturn(mock(Authentication.class)); + this.request.setRequestURI("/example/dispatcher/path/error"); + this.request.setContextPath("/example"); + // Servlet mapped to /dispatcher/path/* + this.request.setServletPath("/dispatcher/path"); + this.securityFilter.doFilter(this.request, this.response, this.filterChain); + verify(this.privilegeEvaluator).isAllowed(eq("/dispatcher/path/error"), any()); + } + } diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/AbstractErrorPageTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/AbstractErrorPageTests.java index 2affea3b3b..22605fe0bc 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/AbstractErrorPageTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/AbstractErrorPageTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -41,6 +41,12 @@ abstract class AbstractErrorPageTests { @Autowired private TestRestTemplate testRestTemplate; + private final String pathPrefix; + + protected AbstractErrorPageTests(String pathPrefix) { + this.pathPrefix = pathPrefix; + } + @Test void testBadCredentials() { final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "wrongpassword") @@ -52,8 +58,8 @@ abstract class AbstractErrorPageTests { @Test void testNoCredentials() { - final ResponseEntity response = this.testRestTemplate.exchange("/test", HttpMethod.GET, null, - JsonNode.class); + final ResponseEntity response = this.testRestTemplate.exchange(this.pathPrefix + "/test", + HttpMethod.GET, null, JsonNode.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); JsonNode jsonResponse = response.getBody(); assertThat(jsonResponse).isNull(); @@ -61,8 +67,8 @@ abstract class AbstractErrorPageTests { @Test void testPublicNotFoundPage() { - final ResponseEntity response = this.testRestTemplate.exchange("/public/notfound", HttpMethod.GET, - null, JsonNode.class); + final ResponseEntity response = this.testRestTemplate.exchange(this.pathPrefix + "/public/notfound", + HttpMethod.GET, null, JsonNode.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); JsonNode jsonResponse = response.getBody(); assertThat(jsonResponse.get("error").asText()).isEqualTo("Not Found"); @@ -71,7 +77,7 @@ abstract class AbstractErrorPageTests { @Test void testPublicNotFoundPageWithCorrectCredentials() { final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "password") - .exchange("/public/notfound", HttpMethod.GET, null, JsonNode.class); + .exchange(this.pathPrefix + "/public/notfound", HttpMethod.GET, null, JsonNode.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); JsonNode jsonResponse = response.getBody(); assertThat(jsonResponse.get("error").asText()).isEqualTo("Not Found"); @@ -80,7 +86,7 @@ abstract class AbstractErrorPageTests { @Test void testPublicNotFoundPageWithBadCredentials() { final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "wrong") - .exchange("/public/notfound", HttpMethod.GET, null, JsonNode.class); + .exchange(this.pathPrefix + "/public/notfound", HttpMethod.GET, null, JsonNode.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); JsonNode jsonResponse = response.getBody(); assertThat(jsonResponse).isNull(); @@ -89,7 +95,7 @@ abstract class AbstractErrorPageTests { @Test void testCorrectCredentialsWithControllerException() { final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "password") - .exchange("/fail", HttpMethod.GET, null, JsonNode.class); + .exchange(this.pathPrefix + "/fail", HttpMethod.GET, null, JsonNode.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); JsonNode jsonResponse = response.getBody(); assertThat(jsonResponse.get("error").asText()).isEqualTo("Internal Server Error"); @@ -98,7 +104,7 @@ abstract class AbstractErrorPageTests { @Test void testCorrectCredentials() { final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "password") - .exchange("/test", HttpMethod.GET, null, String.class); + .exchange(this.pathPrefix + "/test", HttpMethod.GET, null, String.class); assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); response.getBody(); assertThat(response.getBody()).isEqualTo("test"); diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/AbstractUnauthenticatedErrorPageTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/AbstractUnauthenticatedErrorPageTests.java new file mode 100644 index 0000000000..fe15a379bc --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/AbstractUnauthenticatedErrorPageTests.java @@ -0,0 +1,109 @@ +/* + * Copyright 2012-2022 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 + * + * https://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 smoketest.web.secure; + +import com.fasterxml.jackson.databind.JsonNode; +import org.junit.jupiter.api.Test; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.web.client.TestRestTemplate; +import org.springframework.http.HttpMethod; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; + +import static org.assertj.core.api.Assertions.assertThat; + +/** + * Abstract base class for tests to ensure that the error page is accessible only to + * authorized users. + * + * @author Madhura Bhave + */ +abstract class AbstractUnauthenticatedErrorPageTests { + + @Autowired + private TestRestTemplate testRestTemplate; + + private final String pathPrefix; + + protected AbstractUnauthenticatedErrorPageTests(String pathPrefix) { + this.pathPrefix = pathPrefix; + } + + @Test + void testBadCredentials() { + final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "wrongpassword") + .exchange(this.pathPrefix + "/test", HttpMethod.GET, null, JsonNode.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); + JsonNode jsonResponse = response.getBody(); + assertThat(jsonResponse.get("error").asText()).isEqualTo("Unauthorized"); + } + + @Test + void testNoCredentials() { + final ResponseEntity response = this.testRestTemplate.exchange(this.pathPrefix + "/test", + HttpMethod.GET, null, JsonNode.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); + JsonNode jsonResponse = response.getBody(); + assertThat(jsonResponse.get("error").asText()).isEqualTo("Unauthorized"); + } + + @Test + void testPublicNotFoundPage() { + final ResponseEntity response = this.testRestTemplate.exchange(this.pathPrefix + "/public/notfound", + HttpMethod.GET, null, JsonNode.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + JsonNode jsonResponse = response.getBody(); + assertThat(jsonResponse.get("error").asText()).isEqualTo("Not Found"); + } + + @Test + void testPublicNotFoundPageWithCorrectCredentials() { + final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "password") + .exchange(this.pathPrefix + "/public/notfound", HttpMethod.GET, null, JsonNode.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); + JsonNode jsonResponse = response.getBody(); + assertThat(jsonResponse.get("error").asText()).isEqualTo("Not Found"); + } + + @Test + void testPublicNotFoundPageWithBadCredentials() { + final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "wrong") + .exchange(this.pathPrefix + "/public/notfound", HttpMethod.GET, null, JsonNode.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); + JsonNode jsonResponse = response.getBody(); + assertThat(jsonResponse.get("error").asText()).isEqualTo("Unauthorized"); + } + + @Test + void testCorrectCredentialsWithControllerException() { + final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "password") + .exchange(this.pathPrefix + "/fail", HttpMethod.GET, null, JsonNode.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); + JsonNode jsonResponse = response.getBody(); + assertThat(jsonResponse.get("error").asText()).isEqualTo("Internal Server Error"); + } + + @Test + void testCorrectCredentials() { + final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "password") + .exchange(this.pathPrefix + "/test", HttpMethod.GET, null, String.class); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); + assertThat(response.getBody()).isEqualTo("test"); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomContextPathErrorPageTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomContextPathErrorPageTests.java new file mode 100644 index 0000000000..3d422b16dd --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomContextPathErrorPageTests.java @@ -0,0 +1,39 @@ +/* + * Copyright 2012-2022 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 + * + * https://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 smoketest.web.secure; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; + +/** + * Tests to ensure that the error page with a custom context path is accessible only to + * authorized users. + * + * @author Madhura Bhave + */ +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, + classes = { AbstractErrorPageTests.TestConfiguration.class, ErrorPageTests.SecurityConfiguration.class, + SampleWebSecureApplication.class }, + properties = { "server.error.include-message=always", "spring.security.user.name=username", + "spring.security.user.password=password", "server.servlet.context-path=/example" }) +class CustomContextPathErrorPageTests extends AbstractErrorPageTests { + + CustomContextPathErrorPageTests() { + super(""); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomContextPathUnauthenticatedErrorPageTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomContextPathUnauthenticatedErrorPageTests.java new file mode 100644 index 0000000000..653d2eb1a1 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomContextPathUnauthenticatedErrorPageTests.java @@ -0,0 +1,37 @@ +/* + * Copyright 2012-2022 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 + * + * https://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 smoketest.web.secure; + +import org.springframework.boot.test.context.SpringBootTest; + +/** + * Tests for error page that permits access to all with a custom context path. + * + * @author Madhura Bhave + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = { AbstractErrorPageTests.TestConfiguration.class, + UnauthenticatedErrorPageTests.SecurityConfiguration.class, SampleWebSecureApplication.class }, + properties = { "server.error.include-message=always", "spring.security.user.name=username", + "spring.security.user.password=password", "server.servlet.context-path=/example" }) +class CustomContextPathUnauthenticatedErrorPageTests extends AbstractUnauthenticatedErrorPageTests { + + CustomContextPathUnauthenticatedErrorPageTests() { + super(""); + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomServletPathErrorPageTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomServletPathErrorPageTests.java new file mode 100644 index 0000000000..142d59d69f --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomServletPathErrorPageTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2012-2022 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 + * + * https://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 smoketest.web.secure; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +/** + * Tests to ensure that the error page with a custom servlet path is accessible only to + * authorized users. + * + * @author Andy Wilkinson + */ +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT, + classes = { AbstractErrorPageTests.TestConfiguration.class, + CustomServletPathErrorPageTests.SecurityConfiguration.class, SampleWebSecureApplication.class }, + properties = { "server.error.include-message=always", "spring.security.user.name=username", + "spring.security.user.password=password", "spring.mvc.servlet.path=/custom/servlet/path" }) +class CustomServletPathErrorPageTests extends AbstractErrorPageTests { + + CustomServletPathErrorPageTests() { + super("/custom/servlet/path"); + } + + @org.springframework.boot.test.context.TestConfiguration(proxyBeanMethods = false) + static class SecurityConfiguration { + + @Bean + SecurityFilterChain configure(HttpSecurity http) throws Exception { + http.authorizeRequests((requests) -> { + requests.antMatchers("/custom/servlet/path/public/**").permitAll(); + requests.anyRequest().fullyAuthenticated(); + }); + http.httpBasic(); + http.formLogin((form) -> form.loginPage("/custom/servlet/path/login").permitAll()); + return http.build(); + } + + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomServletPathUnauthenticatedErrorPageTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomServletPathUnauthenticatedErrorPageTests.java new file mode 100644 index 0000000000..48190a3d55 --- /dev/null +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/CustomServletPathUnauthenticatedErrorPageTests.java @@ -0,0 +1,57 @@ +/* + * Copyright 2012-2022 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 + * + * https://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 smoketest.web.secure; + +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Bean; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +/** + * Tests for error page that permits access to all with a custom servlet path. + * + * @author Andy Wilkinson + */ +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, + classes = { AbstractErrorPageTests.TestConfiguration.class, + CustomServletPathUnauthenticatedErrorPageTests.SecurityConfiguration.class, + SampleWebSecureApplication.class }, + properties = { "server.error.include-message=always", "spring.security.user.name=username", + "spring.security.user.password=password", "spring.mvc.servlet.path=/custom/servlet/path" }) +class CustomServletPathUnauthenticatedErrorPageTests extends AbstractUnauthenticatedErrorPageTests { + + CustomServletPathUnauthenticatedErrorPageTests() { + super("/custom/servlet/path"); + } + + @org.springframework.boot.test.context.TestConfiguration(proxyBeanMethods = false) + static class SecurityConfiguration { + + @Bean + SecurityFilterChain defaultSecurityFilterChain(HttpSecurity http) throws Exception { + http.authorizeRequests((requests) -> { + requests.antMatchers("/custom/servlet/path/error").permitAll(); + requests.antMatchers("/custom/servlet/path/public/**").permitAll(); + requests.anyRequest().authenticated(); + }); + http.httpBasic(); + return http.build(); + } + + } + +} diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/ErrorPageTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/ErrorPageTests.java index c33ef6deee..99c10a4d42 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/ErrorPageTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/ErrorPageTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -34,6 +34,10 @@ import org.springframework.security.web.SecurityFilterChain; "spring.security.user.password=password" }) class ErrorPageTests extends AbstractErrorPageTests { + ErrorPageTests() { + super(""); + } + @org.springframework.boot.test.context.TestConfiguration(proxyBeanMethods = false) static class SecurityConfiguration { diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/NoSessionErrorPageTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/NoSessionErrorPageTests.java index 9f98a4abcc..0e9ad9043c 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/NoSessionErrorPageTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/NoSessionErrorPageTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -35,6 +35,10 @@ import org.springframework.security.web.SecurityFilterChain; "spring.security.user.password=password" }) class NoSessionErrorPageTests extends AbstractErrorPageTests { + NoSessionErrorPageTests() { + super(""); + } + @org.springframework.boot.test.context.TestConfiguration(proxyBeanMethods = false) static class SecurityConfiguration { diff --git a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/UnauthenticatedErrorPageTests.java b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/UnauthenticatedErrorPageTests.java index df7d92105a..f518bdb202 100644 --- a/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/UnauthenticatedErrorPageTests.java +++ b/spring-boot-tests/spring-boot-smoke-tests/spring-boot-smoke-test-web-secure/src/test/java/smoketest/web/secure/UnauthenticatedErrorPageTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2021 the original author or authors. + * Copyright 2012-2022 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. @@ -16,22 +16,12 @@ package smoketest.web.secure; -import com.fasterxml.jackson.databind.JsonNode; -import org.junit.jupiter.api.Test; - -import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; -import org.springframework.boot.test.web.client.TestRestTemplate; import org.springframework.context.annotation.Bean; -import org.springframework.http.HttpMethod; -import org.springframework.http.HttpStatus; -import org.springframework.http.ResponseEntity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.web.SecurityFilterChain; -import static org.assertj.core.api.Assertions.assertThat; - /** * Tests for error page that permits access to all. * @@ -42,71 +32,10 @@ import static org.assertj.core.api.Assertions.assertThat; UnauthenticatedErrorPageTests.SecurityConfiguration.class, SampleWebSecureApplication.class }, properties = { "server.error.include-message=always", "spring.security.user.name=username", "spring.security.user.password=password" }) -class UnauthenticatedErrorPageTests { - - @Autowired - private TestRestTemplate testRestTemplate; - - @Test - void testBadCredentials() { - final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "wrongpassword") - .exchange("/test", HttpMethod.GET, null, JsonNode.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); - JsonNode jsonResponse = response.getBody(); - assertThat(jsonResponse.get("error").asText()).isEqualTo("Unauthorized"); - } - - @Test - void testNoCredentials() { - final ResponseEntity response = this.testRestTemplate.exchange("/test", HttpMethod.GET, null, - JsonNode.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); - JsonNode jsonResponse = response.getBody(); - assertThat(jsonResponse.get("error").asText()).isEqualTo("Unauthorized"); - } - - @Test - void testPublicNotFoundPage() { - final ResponseEntity response = this.testRestTemplate.exchange("/public/notfound", HttpMethod.GET, - null, JsonNode.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - JsonNode jsonResponse = response.getBody(); - assertThat(jsonResponse.get("error").asText()).isEqualTo("Not Found"); - } - - @Test - void testPublicNotFoundPageWithCorrectCredentials() { - final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "password") - .exchange("/public/notfound", HttpMethod.GET, null, JsonNode.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND); - JsonNode jsonResponse = response.getBody(); - assertThat(jsonResponse.get("error").asText()).isEqualTo("Not Found"); - } - - @Test - void testPublicNotFoundPageWithBadCredentials() { - final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "wrong") - .exchange("/public/notfound", HttpMethod.GET, null, JsonNode.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.UNAUTHORIZED); - JsonNode jsonResponse = response.getBody(); - assertThat(jsonResponse.get("error").asText()).isEqualTo("Unauthorized"); - } - - @Test - void testCorrectCredentialsWithControllerException() { - final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "password") - .exchange("/fail", HttpMethod.GET, null, JsonNode.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); - JsonNode jsonResponse = response.getBody(); - assertThat(jsonResponse.get("error").asText()).isEqualTo("Internal Server Error"); - } +class UnauthenticatedErrorPageTests extends AbstractUnauthenticatedErrorPageTests { - @Test - void testCorrectCredentials() { - final ResponseEntity response = this.testRestTemplate.withBasicAuth("username", "password") - .exchange("/test", HttpMethod.GET, null, String.class); - assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK); - assertThat(response.getBody()).isEqualTo("test"); + UnauthenticatedErrorPageTests() { + super(""); } @org.springframework.boot.test.context.TestConfiguration(proxyBeanMethods = false)