be_better

[Springboot] Test code "csrf" 403 Forbidden 본문

Springboot/Error 해결

[Springboot] Test code "csrf" 403 Forbidden

NiceTry 2024. 1. 9. 22:22

목차

    에러내용

    Springboot 2.x버전으로 프로젝트 진행 중 3.x버전으로 변경하게 되었고 SpringSecurity도 6.x 버전으로 Upgrade를 해야하는 상황이었다.

     

    Springboot, Security 둘다 버전업을 하고 Postman에서 정상적으로 동작하는것까지 확인했는데,

    잘되던 Test Code Controller test에서 말썽이었다.

     

    Controller Test중 Body에는 아무값도 들어있지 않고 403 Forbidden이 발생한 상황

     

    원인

    Spring Security의 어노테이션인 EnableWebSecurity에는 기본적으로 CSRF 공격을 방지하는 기능을 갖고있다.

     

    CSRF(Cross-Site Request Forgery) 공격이란

    사이트 간 요청 위조의 줄임말로

    웹 애플리케이션 취약점 중 하나로 사용자가 자신의 의지와 무관하게 공격자가 의도한 행동을 해서 특정 웹페이지를 보안에 취약하게 한다거나 수정, 삭제 등의 작업을 하게 만드는 공격 방법이다.

     

    이것을 방지하기위해 대표적으로 CSRF Token 방식이 활용되는데,

    우리의 Test code에는 CSRF Token이 존재하지 않아서 접근제한을 둔것이다.

     

    해결

    정말 간단하게 mockMvc.perform uri 요청에 .with(csrf()) 코드를 추가하면 해결할 수 있다.

    mockMvc.perform(post("/api/v1/sign-in")
            .contentType(MediaType.APPLICATION_JSON)
            .content(objectMapper.writeValueAsString(
                new SignInRequest("testUid", "password")
            ))
            .with(csrf()))  // 추가한 부분
        .andExpect(jsonPath("$.result.uid").value("testUid"))
        .andExpect(jsonPath("$.result.roles[0]").value("ROLE_VIEWER"))
        .andExpect(jsonPath("$.result.accessToken").value("testAccessToken"))
        .andExpect(jsonPath("$.result.refreshToken").value("testRefreshToken"))
        .andExpect(status().isOk())
        .andDo(print());

     

    원래 비어있던 Parameters에 {_csrf=[]} 값이 생긴것을 확인할 수 있다.