본문 바로가기
Spring

[Spring Security] POST 테스트 : 403 Forbidden 에러 해결

by soro.k 2023. 5. 17.

 

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());

 

 

 

참고

[보안/인증] CSRF로 인해서, 403에러가 발생했을 때