[스프링 시큐리티] 현재 인증된 유저 객체 참조
구현 코드 커밋
스프링 시큐리티의 스프링 웹 MVC 지원
@AuthenticationPrincipal
- 현재 인증된 Principal을 참조할 수 있도록 지원하는 어노테이션
- Authentication 인터페이스의 구현체(token) 생성자에 전달되는 첫 번째 인자가 Principal
public void login(Account account) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
account.getNickname(), // Principal
account.getPassword(),
List.of(new SimpleGrantedAuthority("ROLE_USER")));
SecurityContext context = SecurityContextHolder.getContext();
context.setAuthentication(token);
}
- UserDetailService에서 Return한 시큐리티의 User 객체를 파라미터로 받을 수 있음
- 시큐리티의 User 객체가 아닌 커스텀한 principal을 사용하고 싶을 때?
@Getter
public class UserAccount extends User {
private Account account;
public UserAccount(Account account){
super(account.getUsername(), account.getPassword(), List.of(new SimpleGrantedAuthority("ROLE_"+ account.getRole())));
this.account = account;
}
}
/* 아래처럼 Authentication(token)을 직접 생성할 경우 함께 변경되어야 함 */
/* */
public void login(Account account) {
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(
new UserAccount(account) // Principal
/* 생략 */
}
- 시큐리티의 User를 상속받는 커스텀 클래스를 작성
- UserDetailService의 구현체에서 loadUserByUsername 메소드를 오버리이딩하여 위에서 작성한 클래스 인스턴스를 반환하도록 하면 커스텀한 Principal(UserAccount) 사용이 가능함
/* class implements UserDetailSerice */
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountRepository.findByUsername(username);
if(account == null){
return null;
}
return new UserAccount(account);
}
- Custom Principal 사용
@GetMapping("/") public String home(@AuthenticationPrincipal UserAccount userAccount, Model model){ ... }
- UserAccount로 전달받으면 Account 객체를 사용하기 위해선 매번 getAccount() 메소드를 호출해야 함
만약 UserDetailService에서 반환하는 User 객체가 아닌 프로젝트 도메인에서 사용하는 User(Account) 객체를 바로 사용하고 싶으면?
- 커스텀 어노테이션
@Retention(RetentionPolicy.RUNTIME) // 어노테이션 유지 범위 @Target(ElementType.PARAMETER) // 어노테이션 적용 위치 @AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : account") public @interface CurrentUser { }
- 인증을 하지 않은 상태면 Principal에 “anonymoususer”가 담겨있음
- 따라서 인증 하지 않은 상태면 null로, 인증된 유저면 Account 객체를 반환
@GetMapping("/")
public String home(@CurrentAccount Account account, Model model){
...
}