
Step 0. 상황
POST method로 코칭 신청 API에 요청을 보내는 테스트 코드를 작성했는데 403 Forbidden이 반환되면서 테스트가 실패했다.
@Nested
@DisplayName("코칭 신청")
class CreateScheduleTest {
@Test
@WithMockCustomUser(role = "MENTEE")
@DisplayName("유효한 스케줄 id가 전달되면 메서드를 호출하고 200 OK를 반환한다.")
void when_scheduleIdIsValid_expect_callMethodAndReturn200Ok() throws Exception {
Long scheduleId = 1L;
ResultActions response =
mockMvc.perform(
MockMvcRequestBuilders.post("/api/v1/mentees/schedule/" + scheduleId))
.andDo(MockMvcResultHandlers.print());
BDDMockito.verify(menteeScheduleService).saveMenteeSchedule(BDDMockito.anyLong(), BDDMockito.anyLong());
response.andExpect(MockMvcResultMatchers.status().isOk());
}
}

Step 1. 원인
같은 로직으로 GET 요청은 성공하는데 왜 POST 요청만 실패하는 건지 살펴보다가 차이점을 발견했다.
GET 요청일 때
{SPRING_SECURITY_CONTEXT=SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=cobook.buddywisdom.global.security.CustomUserDetails@13ea4f97, Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[ROLE_MENTEE]]]}
POST 요청일 때
{org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken@2638500
, SPRING_SECURITY_CONTEXT=SecurityContextImpl [Authentication=UsernamePasswordAuthenticationToken [Principal=cobook.buddywisdom.global.security.CustomUserDetails@71268b8c, Credentials=[PROTECTED], Authenticated=true, Details=null, Granted Authorities=[ROLE_MENTEE]]]}
그렇다. 문제는 CSRF토큰이었다. 처음 든 생각은 스프링 시큐리티 설정 파일에서 csrf() 설정을 disable() 안 했나 했지만 설정 파일에는 이미 설정이 되어있었다.
http.csrf().disable();
Step 2. 해결
다른 분들은 어떻게 하셨는지 찾아보니 시큐리티 설정 파일에서 disable() 해서 해결하거나 테스트 코드에서 직접 CSRF 토큰을 같이 보내줘서 해결하셨다. 나는 이미 같이 하시는 분이 disable() 설정을 해놓으신 상태였는데도 불구하고 403 forbidden이 반환되었기 때문에 테스트 코드에서 직접 토큰을 같이 보내주기로 했다.
ResultActions response =
mockMvc.perform(
MockMvcRequestBuilders.post("/api/v1/mentees/schedule/" + scheduleId)
.with(SecurityMockMvcRequestPostProcessors.csrf()))
.andDo(MockMvcResultHandlers.print());
참고
'Spring' 카테고리의 다른 글
[Spring] Server-Sent Events로 알람 서비스 개선하기 (0) | 2023.08.28 |
---|---|
[Spring] 로컬 캐시를 활용한 Refresh Token 구현기 (feat. Caffeine) (0) | 2023.05.28 |
[Spring] 쉽게 이해하는 Spring Security + JWT 로그인 구현기 (0) | 2023.05.12 |
[Spring] REST Docs 설정 (0) | 2023.04.19 |
[Spring Boot] com.mysql.cj.jdbc.driver not found (0) | 2023.03.31 |