Spring Security 테스트 적용기 02
OAuth 2.0 또는 JWT와 같은 보다 복잡한 인증 메커니즘을 사용하는 경우,
@WithMockUser와 @WithUserDetails만으로는 충분하지 않을 수 있다.
OAuth 2.0 및 JWT와 같은 토큰 기반 인증 방식은 다른 방식으로 테스트해야 한다.
일반적인 방식으로 Spring Security Test 프레임워크에서 지원하는
@WithSecurityContext 애노테이션을 사용하여,
커스텀한 @WithMockUser 애노테이션을 만들고 OAuth 2.0 인증을 가정하는 테스트를 작성할 수 있다.
테스트 코드 작성에 도움을 주는 애노테이션들을 정리하고,
@WithSecurityContext 어노테이션을 사용하여 @WithMockOAuth2User 애노테이션을 만들어 보려고한다.
@AutoConfigureMockMvc
OAuth 2.0 보안을 테스트하기 위해 MockMvc를 설정하는 데 사용되는 애노테이션이다.
MockMvc를 자동으로 구성하고 OAuth 2.0 클라이언트 자격 증명을 처리하는 데 도움을 준다.
@SpringBootTest
@AutoConfigureMockMvc
public class CustomOAuth2UserControllerTest {
// 테스트 코드 작성
}
테스트를 진행할 때 @AuthConfigureMockMvc와 @AuthConfigureRestDocs 가 존재하는데,
MockMvc는 Spring Security를 지원하며, 주입된 사용자 정보를 쉽게 사용할 수 있기 때문에
실제 요청과 좀 더 유사한 MockMvc를 이용하기로 하였다.
@WithMockOauth2User
@WithSecurityContext 어노테이션을 사용하면 사용할 SecurityContext를 지정해 줄 수 있다.
즉 어떤 객체로 바인딩할 것인지를 직접 만들어서 적용할 수 있다.
WithMockOAuth2UserSecurityContextFactory
사용할 SecurityContext를 정의해 줄 클래스이다.
- SecurityContext 객체를 생성
- UserPrincipal에 모의 소셜로그인 사용자를 정의한다.
- Authentication 객체에 유저정보, 비밀번호, 권한 정보를 설정한다.
- SecurityContext는 생성한 Authentication을 설정하고, 이 컨텍스트를 반환한다.
이후 mockmvc 테스트를 진행할 때,
MockMvcBuilders.webAppContextSetup(context)에 이 사용자 정보를 주입하게 된다.
AcceptanceTest
SecurityContext는 생성한 Authentication을 설정하고, 이 콘텍스트를 반환하기 때문에
테스트 메서드에서 @WithMockOAuth2User 어노테이션을 사용하면,
해당 사용자 정보로 보안 컨텍스트가 설정되어 테스트가 실행되는 구조이다.
@WithMockOauth2User를 활용한 사용자 이름 변경 테스트
@Test
@DisplayName("사용자 이름 변경")
@WithMockOAuth2User
void modifyName() throws Exception {
// given
UserNameRequestDto dto = UserNameRequestDto.builder()
.name("김철수").build();
// when
ResultActions result = mockMvc.perform(put("/api/oauth2/user/name")
.header(HttpHeaders.AUTHORIZATION, BEARER_TYPE + "ACCESS_TOKEN")
.content(objectMapper.writeValueAsString(dto))
.contentType(MediaType.APPLICATION_JSON)
);
// then
result.andExpect(status().isOk())
.andDo(document(DEFAULT_RESTDOC_PATH,
requestHeaders(
headerWithName(HttpHeaders.AUTHORIZATION).description("액세스 토큰")
),
requestFields(
fieldWithPath("name").type(JsonFieldType.STRING).description("사용자 이름")
),
responseFields(
fieldWithPath("status").type(JsonFieldType.NUMBER).description("응답 상태 코드"),
fieldWithPath("message").type(JsonFieldType.STRING).description("응답 메시지"),
fieldWithPath("data").type(JsonFieldType.STRING).description("응답 데이터")
)
));
}
header에는 jwt 토큰 예시,
@WithMockOauth2User와의 유저정보와
dto의 이름 정보가 잘 적용된 것을 확인할 수 있다.
정리
이러한 도구와 커스텀한 애노테이션을 사용하여
Spring Security OAuth를 테스트하면 보안 및 인증 관련 시나리오를 다룰 수 있다.
특정 시나리오를 시뮬레이션하고 필요한 인증 및 권한을 설정하는 데 도움 되어 쉽게 테스트 코드를 작성할 수 있었고,
Security의 구조 또한 다시 알아볼 수 있는 경험이 된 것 같다.
reference
'Back-End > Spring' 카테고리의 다른 글
[Spring] Security 테스트 적용기 01 (0) | 2023.10.14 |
---|---|
[Exception] Custom Exception을 언제 써야할까? (0) | 2023.09.18 |
[Spring] Rest-Assured 알아보기 (0) | 2023.08.30 |
[JPA] QueryDSL을 RepositoryImpl로 관리해보자. (0) | 2023.08.05 |
[MVC] DTO 역할 구분, 프로젝트 흐름도 분석 (0) | 2023.05.09 |