1. JWT 인증과 @AuthenticationPrincipal 관계 정리
항목 타입 설명
JWT 토큰 | String | 예: "Bearer xxx.yyy.zzz" 형식. 클라이언트 → 서버 전달용 |
@RequestHeader | String | 요청 헤더에서 토큰 직접 추출. 인증 필터에서 사용됨 |
@AuthenticationPrincipal | UserDetails 또는 CustomUserDetails | 필터에서 토큰을 검증한 후 생성한 사용자 정보 객체 |
결론:
@AuthenticationPrincipal은 "JWT 토큰"이 아닌, 토큰으로 인증한 사용자 객체를 받는 것이므로, 참조 자료형(CustomUserDetails 등) 사용하는 게 맞음.
왜 Security Filter Chain을 꼭 거쳐야 할까?
Spring Security의 기본 인증/인가 흐름:
1. HTTP 요청
↓
2. 🔐 Security Filter Chain
↓
3. 인증(Authentication) → 사용자 정보 확인
↓
4. 인가(Authorization) → ROLE 확인
↓
5. Controller → @AuthenticationPrincipal 사용 가능
필터를 거쳐야 하는 이유
이유 설명
@PreAuthorize("hasRole('ADMIN')") 작동 조건 | SecurityContext에 인증 정보(권한 포함)가 있어야만 작동함 |
필터에서 UsernamePasswordAuthenticationToken 생성 | 이 객체에 Role 정보가 담겨 SecurityContext에 저장됨 |
컨트롤러 이전 단계에서 인가를 걸러냄 | 인가 실패 시 컨트롤러 진입 자체가 차단됨 |
필터 없이 @RequestHeader만 사용할 경우
방식 문제점
@RequestHeader("Authorization")으로 직접 토큰 파싱 | 토큰 검증은 가능하나, Spring Security 권한 처리 불가 |
hasRole(), @Secured, @PreAuthorize 작동 안 함 | SecurityContext에 인증 객체가 없기 때문 |
확장성, 보안성 떨어짐 | 커스터마이징 어려워지고 Spring Security 구조와 충돌 |
결론
Role 기반 인가를 사용하려면 필터에서 반드시 인증 처리 후 SecurityContext에 저장해야 함
→ @AuthenticationPrincipal 사용도 이 흐름에 포함됨.
2. ResponseEntity.ok(user)와 함께 토큰(JWT) 도 자동으로 프론트에 다시 전송되는가?
결론부터 말하자면:
❌ ResponseEntity.ok(user)만으로는 토큰이 다시 전송되지 않음.
✅ 토큰을 다시 응답으로 보내고 싶다면, 명시적으로 응답 헤더나 body에 넣어줘야 함.
이유
JWT는 기본적으로:
- 로그인할 때 1번만 서버에서 발급해서 클라이언트에게 전달
- 이후에는 클라이언트가 그 토큰을 저장해서 직접 요청마다 Authorization 헤더로 전송
- 서버는 보통 토큰을 다시 응답으로 보내지 않음
✅ 예시 비교
❌ 아래처럼 하면 user만 반환됨:
return ResponseEntity.ok(user);
- 이건 단순히 JSON으로 user 객체만 body에 담김
- JWT 토큰은 응답에 포함되지 않음
토큰도 같이 보내고 싶다면?
1) 응답 헤더에 담기
return ResponseEntity.ok()
.header("Authorization", "Bearer " + jwtToken)
.body(user);
2) 응답 Body에 담기 (예: JSON)
Map<String, Object> response = new HashMap<>();
response.put("user", user);
response.put("token", jwtToken);
return ResponseEntity.ok(response);
이 방식은 로그인 API나 토큰 갱신 API에서 주로 사용됨.
단순 사용자 정보 조회 API에서는 토큰을 다시 줄 필요가 없음 (이미 클라이언트가 갖고 있음).
정리
조건 설명
Security 필터 통과 | ✅ @AuthenticationPrincipal 사용 가능 상태 됨 |
ResponseEntity.ok(user) | ❌ 토큰 자동 포함 ❌ (오직 user 정보만 응답됨) |
토큰을 다시 보내려면? | ✅ header 또는 body에 직접 넣어야 함 |
일반적으로 다시 보내야 하나? | ❌ X, 로그인 외엔 보통 다시 보내지 않음 |
'웹 개발 > Spring' 카테고리의 다른 글
Spring Security 인가 DSL 메서드 정리 (0) | 2025.04.25 |
---|---|
Spring security 패턴 매칭 기호(프론트, 백 HTTP통신시 중요) (0) | 2025.04.23 |