Knowledge/Trouble Shooting

@WebMvcTest 테스트 중 에러 코드

똑똑한망치 2024. 7. 9. 16:05
728x90
반응형

❓문제 상황❓

[Test Code]

@WebMvcTest(UserController.class)
class UserControllerTest {

    @MockBean
    private UserService userService;

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private UserRepository userRepository;

    @MockBean
    private JwtTokenProvider jwtTokenProvider;

    @MockBean
    private EmailService emailService;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    @DisplayName("회원가입 성공")
    void signup_success() throws Exception {
        // given
        SignUpForm signUpForm = SignUpForm.builder()
                .loginId("test")
                .password("test")
                .email("test@naver.com")
                .build();

        UserDto userDto = UserDto.builder()
                .loginId("test")
                .email("test@naver.com")
                .verifiedStatus(false)
                .build();

        // when
        when(userService.signUp(signUpForm)).thenReturn(userDto);

        // then
        mockMvc.perform(post("/user/signup")
                        .contentType(MediaType.APPLICATION_JSON)
                        .content(objectMapper.writeValueAsString(signUpForm))
                        .with(csrf())
                )
                .andDo(print())
                .andExpect(status().isOk());
    }

 

 

(1) 401 오류

 

 

Test 코드 실행 시 401에러가 발생한다. 그 이유는 Security가 모든 요청에 대해 권한을 요구하기 때문에 현재 코드에서는 권한을 따로 주고 있지 않기 때문에 오류가 발생했다.

 

✅ 401 오류 해결방안

요청을 할 때 권한을 같이 넘겨줘야 한다.

어노테이션을 사용해 권한을 넘겨주는 방법을 통해 해결할 수 있다.

  • @WithMockUser - 인증된 사용자
  • @WithAnonymousUser - 미인증 사용자
  • @WithUserDetails - 메서드가 Principal 내부의 값을 직접 사용하는 경우 (별도의 사전 설정 필요)

따라서 @WithMockUser을 붙여주게 되면 권한은 있기 때문에 401 오류는 해결 된다.

 

 

(2) 403 오류

 

403 오류는 Security에서 로그인은 했지만 권한이 맞지 않기 때문에 발생하는 오류이다.

 

✅ 403 오류 해결방안

Spring Security Test 에서 403 오류는 csrf 때문에 발생한다고 한다.

 

csrf 란?

  • 공격자가 악의적인 코드를 심어놓은 사이트를 만들어놓고, 로그인 된 사용자가 클릭하게 만들어 사용자 의지와 무관한 요청을 발생시키는 공격
  • 로그인 한 상태에서 사용자가 해킹 사이트에 접속 시 공격자는 해당 유저의 저보를 빼가고 그 정보를 가지고 메인 서버로부터 그 유저의 개인정보를 호출하여 정보를 빼가는 방식이다. 즉, POST, UPDATE, DELETE와 같이 작업하는 기능들이나 중요한 정보를 호출하는 부분인 GET에 대해서는 csrf를 적용하고 있다.
  • 따라서 이러한 문제점을 방지하기 위해 csrf 토큰을 사용하는데 토큰 값을 비교해서 일치하는 경우에만 메서드를 처리하도록 한다.
  • 서버가 뷰를 만들 때 사용자 별 csrf 랜덤값을 만들어 세션에 로그인 정보와 같이 담아 HTTP 요청마다 csrf 토큰을 같이 넘겨 준다. 이 때, 서버는 매 페이지마다 csrf 토큰값과 세션에 저장되어 있는 토큰값을 비교해 일치한 경우에만 처리를 진행한다.

따라서 Test 코드에서도 csrf의 주소 값을 Http 요청할 때 넣어서 같이 보내줘야 한다.

.with(csrf())) 를 통해 담아준다.

반응형