@WithMockUser
스프링 시큐리티를 사용하면 시큐리티 컨텍스트에서 Principal 정보를 꺼내 쓸 수 있다.
따라서 인증 완료된 유저는 컨트롤러에서 @AuthenticationPrincipal 을 사용하여 사용자 정보를 이용하곤 한다.
하지만 컨트롤러 테스트를 할 때 컨트롤러를 호출하면 인증을 하지 않았기 때문에 UserPrincipal 객체가 null일 것이다.
당연히 실제 환경처럼 컨트롤러 호출 시 쿠키에 Jwt를 넣는 등의 인증 과정을 거치면 되겠지만,
매 테스트마다 유효한 Jwt를 만들어서 넣어줘야한다는 문제가 생긴다.
유저 정보를 DB에 넣고, 유저 정보로 Jwt를 만들고, 요청에 넣어주는건 굉장히 번거롭다.
이런 번거로움을 해소하기 위해 스프링 시큐리티에서는 @WithMockUser 라는 애노테이션을 제공한다.
이를 이용하면 시큐리티 컨텍스트에 MockUser 정보를 넣어두기 때문에 인증 없이 컨트롤러를 호출해도 문제없이 사용할 수 있다.
하지만 서비스마다 유저 객체 정보가 다르기 때문에 기본적인 @WithMockUser 를 사용하기에는 한계가 있다.
따라서 이번 글에서는 @WithMockUser 를 커스텀해서 사용하여 서비스에 맞는 MockUser 정보를 이용해볼 것이다.
1. 구현
CustomMockSecurityContext
MockSecurityContext를 만든다.
아래처럼 WithSecurityContextFactory를 구현하고, 시큐리티 컨텍스트에 MockUser 정보를 넣어준다.
@RequiredArgsConstructor
public class PawLandMockSecurityContext implements WithSecurityContextFactory<PawLandMockUser> {
private final UserRepository userRepository;
@Override
public SecurityContext createSecurityContext(PawLandMockUser annotation) {
User user = User.builder()
.email(annotation.email())
.nickname(annotation.nickname())
.password(annotation.password())
.type(annotation.type())
.profileImage(annotation.profileImage())
.introduce(annotation.getIntroduce())
.build();
userRepository.save(user);
UserPrincipal userPrincipal = new UserPrincipal(user);
SimpleGrantedAuthority role = new SimpleGrantedAuthority(annotation.role());
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(userPrincipal,
user.getPassword(),
List.of(role));
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(authenticationToken);
return context;
}
}
CustomMockUser
이제 위에서 만든 Mock 시큐리티 컨텍스트를 사용할 커스텀 MockUser 애노테이션을 만든다.
아래처럼 원하는 필드를 설정하고, 기본 값을 정해주면 애노테이션을 붙이면 설정한 MockUser 정보를 이용한다.
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = PawLandMockSecurityContext.class)
public @interface PawLandMockUser {
String email() default "midcondria@naver.com";
String nickname() default "나는짱";
String password() default "asd123123";
String profileImage() default "";
String getIntroduce() default "";
LoginType type() default LoginType.NORMAL;
String role() default "ROLE_USER";
}
2. 사용하기
1. 애노테이션만 붙일 때
아래처럼 애노테이션만 붙이면 기본 값으로 설정한 정보를 사용한다.
2. 애노테이션에 원하는 값을 넣을 수 있음
아래처럼 애노테이션에 원하는 값을 넣으면 원하는 설정한 정보를 사용할 수 있다.
'백엔드 > Spring Security' 카테고리의 다른 글
비로그인 사용자의 권한 처리: 메서드 시큐리티 적용 (0) | 2024.05.14 |
---|---|
시큐리티 환경에서 테스트 2: 컨트롤러 테스트하기 (0) | 2024.04.25 |
JwtFilter 만들기 (0) | 2024.04.16 |