Notice
Recent Posts
Link
Tags
- select
- DI
- Docker
- java
- 스프링
- PYTHON
- springboot
- 프로그래머스
- sql
- 1차원 배열
- spring
- hibernate
- 데이터베이스
- spring mvc
- Django
- 자바
- mysql
- join
- jpa
- 스프링부트
- AWS
- string
- 문자열
- SSL
- @transactional
- static
- spring boot
- ORM
- spring security 6
- nginx
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
31 |
Archives
개발하는 자몽
[Spring Security] @CurrentUser 본문
스프링 시큐리티는 `@AuthenticationPrincipal` 애노테이션을 제공한다. 이는 `Authenticaiton.getPrincipal()`를 메서드 인자로 가져오는 데 사용되며, 보통은 `UserDetails` 타입이나 해당 타입의 커스텀 구현체로 가져오게 된다.
`Authentication.getPrincipal()`에는 username, password(AuthenticationManager 구현에 따라 없을 수 있음), role과 같은 사용자 정보가 담겨있다.
간단하게 해당 애노테이션을 그대로 사용해도 되지만, 더 편리하게 사용할 수 있다. 이는 공식문서에서도 안내하고 있다.
실제로 구현해 보자. 여기서는 커스텀 애노테이션 이름을 `@CurrentUser`로 설정했다.
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import java.lang.annotation.*;
/**
* 익명 사용자인 경우에는 null로, 익명 사용자가 아닌 경우에는 실제 Users 객체로
*/
@Target({ElementType.PARAMETER, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : user")
public @interface CurrentUser {
}
`@AuthenticationPrincipal.expression`에 SpEL 표현식을 사용하여 원하는 값을 가져오도록 설정할 수 있다. 위 표현식은 다음을 의미한다.
- 현재 객체(`#this`)가 익명 사용자(`anonymousUser`, 인증되지 않음)라면 `null`을 반환
- 아니라면, `Authentication.getPrincipal()`을 통해 사용자를 나타내는 객체(`UserDetails` 또는 다른 구현체)를 반환
구현을 완료하면 다음과 같이 사용자 객체를 간편하게 애노테이션으로 가져올 수 있다.
...
public class UserController {
...
@GetMapping("/info")
public ResponseEntity<ResponseBody<UserInfo>> getInfo(@CurrentUser Users user) {
UserInfo userInfo = userInfoService.get(user);
return ResponseUtil.from(HttpStatus.OK.value(), userInfo);
}
...
}
참고로 위에서 사용한 `Users` 객체는 직접 정의한 도메인 객체이다. `UserDetails` 구현체는 아니지만, `UserDetailsService. loadUserByUsername`에서 `UserDetails` 구현체를 생성하여 반환할 때 `Users` 객체를 인자로 넣어주고 있어서 가능하다.
public class UserDetailsServiceImpl implements UserDetailsService {
private final UserRepository userRepository;
@Override
public UserDetails loadUserByUsername(String email) {
Users user = userRepository.findByEmail(email)
.orElseThrow(() -> new UsernameNotFoundException(NOT_FOUND_USER.getMessage()));
return new CustomUserDetails(user); // 커스텀 UserDetails 클래스 생성자에 직접 구현한 Users 객체를 인자로 넘김
}
}
'Java & Kotlin > Spring' 카테고리의 다른 글
[Spring Security] 세션 기반 로그인 구현하기 (0) | 2025.07.05 |
---|---|
[Spring Security] OAuth2 카카오 로그인 구현 with JWT (1) | 2024.12.29 |
[Spring] @Value과 static 변수 (0) | 2024.12.16 |
[Spring Data JPA] 하이버네이트 Batch Size (1) | 2024.11.25 |
[JPA Error] No EntityManager with actual transaction available for current thread - cannot reliably process 'flush' call (0) | 2024.10.23 |
Comments