1. SecurityContext
Authentication authentication =
SecurityContextHolder.getContext().getAuthentication();
CustomUser custom = (CustomUser) authentication == null ? null : authentication.getPrincipal();
스프링 시큐리티는 SecurityContext라는 인터페이스에 인증 정보를 저장하기 때문에 Principal을 이용하여 유저의 name을 가져올 수 있지만,
Controller의 코드가 지저분해지고, 정보가 한정적이다.
2. @AuthenticationPrincipal
Spring Security 3.2부터 @AuthenticationPrincipal를 이용하여 간결히 사용할 수 있다.
@AuthenticationPrincipal 는 UserDetails를 구현한 객체를 통해 반환된 사용자 정보를 가져온다.
public class CustomUserUserDetails extends User {
// ...
public CustomUser getCustomUser() {
return customUser;
}
}
보다 많은 정보를 가져오기 위해서 다음과 같이 유저를 커스텀하고 이를 userDetailsService에서 반환받아야 한다.
CustomUserDetails.java
@Getter
public class CustomUserDetails extends User {
private final UserEntity userEntity;
public CustomUserDetails(UserEntity userEntity) {
super(userEntity.getUsername(),
userEntity.getPassword(),
List.of(new SimpleGrantedAuthority("USER")));
this.userEntity = userEntity;
}
}
CustomUserDetailsService.java
@Override
public CustomUserDetails loadUserByUsername(String username) {
UserEntity userEntity = userRepository.findByUsername(username)
.orElseThrow(() -> new UsernameNotFoundException("해당하는 아이디가 존재하지 않습니다."));
return new CustomUserDetails(userEntity);
}
Controller
@GetMapping("/")
public String getHomepage(@AuthenticationPrincipal UserEntity userEntity, Model model) {
if (customUserDetails != null) {
model.addAttribute("currentUser", userEntity.username);
}
return "page/HomePage";
}
getAccount() 메서드를 호출하여 계정 정보를 가져오며, 익명 유저를 구분해내지 못한다.
따라서 아래와 같이 SpEL(Sptring Expression Language) 표현식으로 익명 유저를 제외한다.
@GetMapping("/")
public String getHomepage(@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : userEntity") UserEntity userEntity, Model model) {
if (customUserDetails != null) {
model.addAttribute("currentUser", userEntity.username);
}
return "page/HomePage";
}
다만 매개변수가 너무 길어서 가독성이 떨어지므로 다음과 같이 커스텀 어노테이션을 만들 수 있다.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : userEntity")
public @interface CurrentUser {
}
@GetMapping("/")
public String getHomepage(@CurrentUser UserEntity userEntity, Model model) {
if (customUserDetails != null) {
model.addAttribute("currentUser", userEntity.username);
}
return "page/HomePage";
}
참고 사이트
- https://docs.spring.io/spring-security/reference/servlet/integrations/mvc.html
- https://frogand.tistory.com/190
'Backend > Spring' 카테고리의 다른 글
API 요청 - RestTemplate, WebClient, RestClient (1) | 2024.11.07 |
---|---|
YAML 설정 값 가져오기 (0) | 2024.11.06 |
JDBC 이해 (0) | 2024.08.25 |
파일 업로드 (0) | 2024.08.23 |
[SpringBoot] JPA - PersistentBag (0) | 2024.03.27 |