Spring Security
를 팀플에 적용하면서 필요해졌다.
SecurityContext
를 이용해서 인증 정보를 받아, HTTP 요청에서 사용자에 대한 추가 정보를 얻지 않도록 하고 싶었다.
결론으로 Long userId
이거를 로직에서 지워버리고 싶었다.
하지만, JWT 필터를 통해 SecurityContext
를 만들어준 다음에는 Authentication 객체로 받게 된다.
이렇게 되면, 다른 팀원들이 인증 정보에서 무언가를 꺼내서 쓰려면 매번 파싱해주고, 형변환해주고 그래야 한다.
중복코드가 엄청 발생
할 것.
그래서 편하게 인증정보를 꺼내쓸 수 있는 클래스를 만들어서 주고 싶었다.
팀원들이 Security 프레임워크를 모르더라도 사용할 수 있도록 하려고 JwtSimpleAuthentication
이라는 클래스를 만들었다.
@Component
public class JwtSimpleAuthentication {
public Email getEmail() {
JwtAuthenticationPrincipal principal = (JwtAuthenticationPrincipal) SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
return new Email(principal.email());
}
public String getEmailAddress() {
JwtAuthenticationPrincipal principal = (JwtAuthenticationPrincipal) SecurityContextHolder.getContext()
.getAuthentication()
.getPrincipal();
return principal.email();
}
public Role getRole() {
List<GrantedAuthority> authorities = (List<GrantedAuthority>) SecurityContextHolder.getContext()
.getAuthentication()
.getAuthorities();
return Role.valueOf(authorities.get(0)
.getAuthority());
}
}
public record JwtAuthenticationPrincipal(String email) {
public JwtAuthenticationPrincipal {
Assert.isTrue(isNotEmpty(email), "email must be provided.");
}
}
@Component
public class Service {
private final JwtSimpleAuthentication authentication;
public Service(JwtSimpleAuthentication authentication) {
this.authentication = authentication;
}
public String test() {
Email email = authentication.getEmail();
Role role = authentication.getRole();
return authentication.getEmailAddress();
}
}
JwtSimpleAuthentication
객체를 사용한 메소드 테스트할 때가 문제였습니다.@WithMockCustomUser
을 사용하면 이제 처리됩니다.@SpringBootTest
@Transactional
class UserServiceTest {
@Autowired
private UserService userService;
@Test
@WithMockCustomUser
void test() {
String test = userService.test();
System.out.println(test);
}
}
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@WithSecurityContext(factory = WithMockCustomUserSecurityContextFactory.class)
public @interface WithMockCustomUser {
String email() default "danaka@naver.com";
String role() default "USER";
}
@WithMockCustomUser
어노테이션 사용 시 이메일과 역할이 고정된다.