be_better

[Springboot] test code mockmvc perform header에 jwt 권한 인증처리 본문

Springboot/코딩

[Springboot] test code mockmvc perform header에 jwt 권한 인증처리

NiceTry 2023. 12. 29. 17:58

목차

    프로젝트 진행중에

    유저 정보를 update 하는 api를 unit 테스트 하려는데,

    header 값으로 넣어줄 jwt accessToken에 대한 유저권한처리가 안돼서 발목을 잡혔다.

     

    해결

    SecurityConfig에서 SecurityContext에 유저 권한을 넣어주고 Filter에서 처리하는데

    test code를 실행할때도 main module의 SecurityContext를 참조하기 때문에 유저 역할(권한) 처리가 안되는 것이라고 이해했다.

     

    따라서 test module에서 따로 SecurityContext에 필요한 권한을 넣어줘야 한다.

     

    나같은 경우에는 유저 정보 update api는 "USER_VIEWER" 권한을 갖는 유저만 접근할 수 있다.

     

    매번 권한을 설정하는것보다 어노테이션을 만드는게 나아서 customAnnotation을 만들어 사용한다.

     

    어노테이션 정의
    /**
     * token 권한이 필요한 test method 에 적용하는 Annotation
     */
    @Retention(RetentionPolicy.RUNTIME)
    @WithSecurityContext(factory = WithCustomMockUserSecurityContextFactory.class)
    public @interface WithCustomMockUser {
      String uid() default "testId";
    }

     

    어노테이션 구현
    /**
     * security config 와의 의존성을 깨고 test 할때만 사용하게되는 SecurityContext 재설정 class
     */
    public class WithCustomMockUserSecurityContextFactory implements
        WithSecurityContextFactory<WithCustomMockUser> {
    
      @Override
      public SecurityContext createSecurityContext(WithCustomMockUser annotation) {
        String uid = annotation.uid();
    
        Authentication auth = new UsernamePasswordAuthenticationToken(uid, "",
            List.of(new SimpleGrantedAuthority("ROLE_VIEWER")));
    
        SecurityContext context = SecurityContextHolder.getContext();
        context.setAuthentication(auth);
    
        return context;
      }
    }

     

    test코드에 적용
    @Test
    @WithCustomMockUser
    @DisplayName("유저 정보 변경 성공")
    void success_modify_user() throws Exception {
    
      ...(생략)
      
      mockMvc.perform(multipart(HttpMethod.PUT, "/api/v1/user/1")
              .file(image)
              .file(new MockMultipartFile("request", "", "application/json",
                  valueAsString.getBytes(StandardCharsets.UTF_8)))
              .contentType(MediaType.MULTIPART_FORM_DATA)
              .accept(MediaType.APPLICATION_JSON)
              .characterEncoding("UTF-8")
              .with(csrf())
              .header("X-AUTH-TOKEN", "testAccessToken"))
    
          .andExpect(status().isOk())
          .andDo(print());
    }

    • MultipartFile 인터페이스로 image를 받아야 하기 때문에 multipart("uri") 메소드 사용
    • HttpMethod.PUT 설정을 해주지 않으면 자동으로 POST Method가 적용된다.
    • 필요한 header의 키값은 "X-AUTH-TOKEN"이고 value값으로 아무 토큰값을 입력해준다.
    • @WithCustomMockUser 어노테이션에서 SecurityContext auth에 USER_VIEWER 권한을 넣어줬기 때문에 이상없이 실행 가능

     

    참조링크

    테스트코드 Header jwt 권한 설정

     

    [Spring Security + JWT] Spring Security Controller Unit Test하기

    Unit Test로 더 작은 단위로 쪼개기 위해서 Controller, Service, Repository 계층별로 테스트를 진행해야 했습니다.하지만, Controller는 Spring Security와 JWT와 깊은 의존성을 가지고 있어 별도의 처리를 해야했

    velog.io