문제상황
@PostMapping()
public ResponseEntity<? extends BaseResponseBody> createConference(@AuthenticationPrincipal SsafyUserDetails userDetails) {
conferenceService.createConference(userDetails.getUser().getUserId());
return ResponseEntity.status(201).body(BaseResponseBody.of(201, "Success"));
}
프로젝트를 진행할 때 SpringSecurity와 JWT Token 기술이 적용된 스켈레톤 코드를 받아서 진행하는데 늘 사용하던 @AuthenticationPrincipal 어노테이션을 사용하니 UserDetails 인터페이스를 구현한 클래스가 계속 null 값이 떴다.
문제원인
사용자 요청이 들어오면 AuthenticationFilter가 요청을 가로챈 후 getAuthentication() 메서드로 UsernamePasswordAuthenticationToken 객체를 생성하는데 이때 토큰의 파라미터로 String 값인 userId를 넣어준 것이 원인이었다.
/**
* 요청 헤더에 jwt 토큰이 있는 경우, 토큰 검증 및 인증 처리 로직 정의.
*/
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {
...
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
...
try {
Authentication authentication = getAuthentication(request);
// jwt 토큰으로 부터 획득한 인증 정보(authentication) 설정.
SecurityContextHolder.getContext().setAuthentication(authentication);
}
...
}
@Transactional(readOnly = true)
public Authentication getAuthentication(HttpServletRequest request) throws Exception {
...
// 식별된 정상 유저인 경우, 요청 context 내에서 참조 가능한 인증 정보(jwtAuthentication) 생성.
SsafyUserDetails userDetails = new SsafyUserDetails(user);
UsernamePasswordAuthenticationToken jwtAuthentication = new UsernamePasswordAuthenticationToken(userId,
null, userDetails.getAuthorities());
...
}
}
해결방법
아래와 같이 첫번째 파라미터인 userId를 UserDetails 인터페이스를 구현한 클래스로 바꿔주었더니 UserDetails 구현클래스가 잘 넘어온 것을 확인할 수 있었다.
@Transactional(readOnly = true)
public Authentication getAuthentication(HttpServletRequest request) throws Exception {
...
// 식별된 정상 유저인 경우, 요청 context 내에서 참조 가능한 인증 정보(jwtAuthentication) 생성.
SsafyUserDetails userDetails = new SsafyUserDetails(user);
UsernamePasswordAuthenticationToken jwtAuthentication = new UsernamePasswordAuthenticationToken(userDetails,
null, userDetails.getAuthorities());
...
}
'Spring' 카테고리의 다른 글
[Spring] ThreadLocal이란? (0) | 2023.03.08 |
---|---|
[Spring] Interceptor와 ServletFilter의 차이 (0) | 2023.03.07 |
동시성 이슈 해결방법 (Synchronized, DB Lock, Redis Lock) (0) | 2022.12.20 |
리팩토링 (1) | 2022.12.02 |
[Spring] 스프링 빈 설정 (XML, JAVA, Component Scan) (0) | 2022.11.08 |