개요
Spring Test 를 작성하려고 하다보면, 인증이 필요한 부분이 있습니다.
인증이 필요한 부분에 간단하게 인증을 추가할 수 있는 방법을 소개하겠습니다.
해당 내용은 모두 스프링 공식 문서에서 확인할 수 있습니다.[https://docs.spring.io/spring-security/site/docs/current/reference/html5/#test-method]
Annotation
- 기본적으로 SecrutityContext 는 method 테스트 직전에 초기화 되는데, 옵션을 통해 테스트 실행시에 한번만 초기화 되도록 할 수 있습니다
@WithMockUser(setupBefore = TestExecutionEvent.TEST_EXECUTION)
@WithMockUser
- username, roles, authorities 등의 속성을 통해 어떤 사용자를 mocking 할 것인지 설정합니다.
- roles : 설정한 값에 ROLE_ prefix 를 붙입니다.
- authorities : prefix 를 붙이지 않습니다.
@Test @WithMockUser(username = "test", roles = {"USER", "ADMIN"}) void admin() throws Exception { mockMvc.perform(get("/admin")) .andDo(print()) .andExpect(status().isOk()); }
@WithAnonymousUser
- 익명 사용자 (인증이 필요하지 않은 부분) 를 mocking 합니다
@WithSecurityContext
SecurityContext 를 커스텀하게 생성하여 사용하도록 설정합니다
먼저 커스텀한 어노테이션을 생성합니다.(SecurityContext 를 생성할 곳을 마킹하는 어노테이션)
@Retention(RetentionPolicy.RUNTIME) @WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class) public @interface WithMockCustomUser { String username() default "test"; String name() default "name"; }
WithSecurityContextFactory<커스텀어노테이션> 을 구현하는 factory class 를 정의합니다. (실제 SecurityContext 를 생성해주는 class)
import com.github.prgrms.social.model.user.Email;
import com.github.prgrms.social.model.user.Role;
import com.github.prgrms.social.security.JwtAuthentication;
import com.github.prgrms.social.security.JwtAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.test.context.support.WithSecurityContextFactory;
import static org.springframework.security.core.authority.AuthorityUtils.createAuthorityList;
public class WithMockCustomUserSecurityContextFactory
implements WithSecurityContextFactory<WithMockCustomUser> {
@Override
public SecurityContext createSecurityContext(WithMockCustomUser annotation) {
final SecurityContext context = SecurityContextHolder.createEmptyContext();
// Authentication 은 본인이 인증에 사용하는 클래스를 생성하면 됩니다.
final Authentication auth = new JwtAuthenticationToken(
new JwtAuthentication(1L, "tester", new Email("test00@gmail.com")),
null,
createAuthorityList(Role.USER.value())
);
context.setAuthentication(auth);
return context;
}
}
마지막으로 실제 사용방법입니다 어노테이션을 달아줌으로써 해당 메서드는 인증된 정보가 들어있는 SecurityContext 를 받게 됩니다.
@Test @WithMockCustomUser void like() throws Exception { Post mockPost = new Post.Builder() .seq(1L) .userId(Id.of(User.class, 1L)) .writer(new Writer(new Email("test@test.com"))) .contents("contents") .likes(1) .likesOfMe(true) .build(); given(postService.like(any(), any(), any())).willReturn(Optional.of(mockPost)); mockMvc.perform(patch("/api/user/1/post/1/like") .header("api_key", "Bearer " + token)) .andDo(print()) .andExpect(status().isOk()) .andExpect(jsonPath("$.response.likesOfMe").value(true)); }
기타
- SecurityMockMvcRequestPostProcessors 를 이용한 방법이 있습니다.
- 아래와 같이 with 메서드의 인자로 custom 하게 사용이 가능합니다. 제공하는 메서드들이 꽤나 많이 있습니다. 궁금하신점은 spring 공식 문서를 참고하면 많은 내용이 있습니다.
mockMvc.perform(post("/").with(user("user").password("pass").roles("USER")))
실무에서 스프링 시큐리티를 사용하지 않아서, 스터디를 통해 커스텀하게 사용하는 방법과 그에 따라 테스트를 만드는 방법에 대해 공부하는 계기가 되었습니다. 스프링 레퍼런스가 워낙 방대하다보니 내용을 하나하나 찾기가 참 어려운거 같습니다.
'Spring > Spring Security' 카테고리의 다른 글
Spring Security (5) - SecurityContextPersistenceFilter (0) | 2020.12.08 |
---|---|
Spring Security (4) - 기본설정과 JPA 연동 (0) | 2020.09.15 |
Spring Security (3) - Authentication (0) | 2020.09.09 |
Spring Security(2) - SecurityContext (0) | 2020.09.01 |
Spring Security (1) - FilterChainProxy (2) | 2020.08.11 |