-
Notifications
You must be signed in to change notification settings - Fork 129
Description
problem-spring-web
fails to work with Spring Security after upgrading to Spring Boot 2.5
Description
After introducing spring-security
as dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
problem-spring-web
will no longer work.
Expected Behavior
Work as expected.
For example, normally with problem-spring-web
, a validation failure message looks like below:
{
"title": "Bad Request",
"status": 400,
"detail": "Required request parameter 'message' for method parameter type String is not present"
}
Actual Behavior
-
Authentication failure will cause empty response with status 200.
-
Application will simply respond as Spring Boot's default beheavior will do on other expections thrown:
{
"timestamp": "2021-11-10T00:00:00.000+00:00",
"status": 400,
"error": "Bad Request",
"path": "/echo"
}
Possible Fix
I personally have no idea about this
Steps to Reproduce
- Create a new project using Spring Initializr
- Include
problem-spring-web
as dependency:
<dependency>
<groupId>org.zalando</groupId>
<artifactId>problem-spring-web-starter</artifactId>
<version>0.27.0</version>
</dependency>
- Prepare a ValueObject
@Data(staticConstructor = "of")
@AllArgsConstructor
public class EchoMessage {
String message;
}
- Prepare a RestController
@RestController
public class EchoController {
@GetMapping(value = {"/echo", "/authorized/echo"})
public EchoMessage echo(@RequestParam @NotEmpty String message) {
return EchoMessage.of(message);
}
}
- Configure Spring security
@Configuration
public class SecurityConfiguration {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
// @formatter:off
return http
.authorizeRequests()
.antMatchers("/authorized/**")
.authenticated()
.anyRequest()
.anonymous()
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf()
.disable()
.httpBasic()
.disable()
.build();
// @formatter:on
}
}
- Write tests
@WebMvcTest
@ContextConfiguration(classes = SecurityTestConfiguration.class)
public class EchoControllerTest {
private final MockMvc mockMvc;
@Autowired
public EchoControllerTest(MockMvc mockMvc) {
this.mockMvc = mockMvc;
}
@Test
public void testEcho() throws Exception {
this.mockMvc.perform(get("/echo?message={message}", "Hello"))
.andExpect(status().is(200))
.andExpect(jsonPath("$.message", is("Hello")));
}
@Test
public void testEchoWithoutMessage() throws Exception {
this.mockMvc.perform(get("/echo"))
.andExpect(header().string("Content-Type", "application/problem+json"))
.andExpect(status().is(400))
.andExpect(jsonPath("$.title", is("Bad Request")))
.andExpect(jsonPath("$.status", is(400)));
}
@Test
public void testEchoPost() throws Exception {
this.mockMvc.perform(post("/echo?message={message}", "Hello"))
.andExpect(header().string("Content-Type", "application/problem+json"))
.andExpect(status().is(405))
.andExpect(jsonPath("$.title", is("Method Not Allowed")))
.andExpect(jsonPath("$.status", is(405)));
}
@Test
public void testAuthorizedEcho() throws Exception {
this.mockMvc.perform(get("/authorized/echo?message={message}", "Hello"))
.andExpect(header().string("Content-Type", "application/problem+json"))
.andExpect(status().is(401))
.andExpect(jsonPath("$.title", is("Unauthorized")))
.andExpect(jsonPath("$.status", is(401)));
}
}
All tests fails except for testEcho
.
I also tried simulating requests to /echo
using curl
, and got the same result.
Context
I find that if I register my own AdivceTrait bean in SecurityConfiguration
, problem-spring-web
will work again:
@Configuration
public class SecurityConfiguration {
@ControllerAdvice
public static class SecurityExceptionHandling implements ProblemHandling, SecurityAdviceTrait {}
@Bean
public AdviceTrait securityExceptionHandling() {
return new SecurityExceptionHandling();
}
// Other beans
}
Your Environment
- Spring Boot version: 2.5.6
problem-spring-web
version: 0.27.0- Java version: Adopt OpenJDK 11
AND here is the runnable demo project attached: demo.zip