-
WebSocket 연결 시, JWT Token Error트러블슈팅 2024. 8. 15. 20:29
문제
다른 요청에 대해서는 header의 token을 정상적으로 가져오지만 Web Socket의 요청에서 계속 Spring Security Context 에서 사용자의 정보를 가져올 때, 에러가 발생했다.
원인
- 정상적인 요청
Jul 23 09:24:38 ip-172-31-44-203 web[1099434]: token : Bearer aaaaaaaaabbbbbbbbbbbcccccccc
- websocket 의 요청
Jul 23 09:22:29 ip-172-31-44-203 web[1099434]: token : null
- http와 WebSocket의 Security chain, config는 완전히 독립적이다.
- 기존 AuthenticationProvider는 Websocket Authentication에 관여하지 않는다.
- Websocket에 CONNECT 되면 해당 user는 websocket session에 저장되며 이후 메세지에는 인증 과정을 거치지 않는다.
해결
- WebSocketConfig
@Override public void configureClientInboundChannel(ChannelRegistration registration) { registration.interceptors(stompHandler); }
- StompHandler
@Component @RequiredArgsConstructor public class StompHandler implements ChannelInterceptor { private final JwtUtil jwtUtil; @Override public Message<?> preSend(Message<?> message, MessageChannel channel) { StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message); String accessToken = ""; // 연결 요청에 대해 실행 if(accessor.getCommand() == StompCommand.CONNECT) { accessToken = accessor.getFirstNativeHeader("Authorization"); } if (StringUtils.hasText(accessToken) && accessToken.startsWith("Bearer ")) { accessToken = accessToken.substring(7); } try { jwtUtil.validateAccessToken(accessToken); } catch (ExpiredJwtException e) { throw new CatchStudyException(ErrorCode.EXPIRED_ACCESS_TOKEN); } Authentication authentication = jwtUtil.getAuthentication(accessToken); SecurityContextHolder.getContext().setAuthentication(authentication); accessor.setUser(authentication); return message; } }
WebSocketConfig에 ChannelInterceptor를 구현한 클래스를 만들어 stomp 메시지 헤더에 접근해 socket이 연결되었을 때,
token을 검증하도록 했다.
'트러블슈팅' 카테고리의 다른 글
STOMP 메시지 전송 시 security context holder에서 유저 정보를 가져올 수 없는 error (0) 2024.08.16 STOMP 연결, 해제 시 header 값 Error (0) 2024.08.15 Redis protected mode Error (0) 2024.08.15 spring security oauth2.0 kakao error (0) 2024.08.15 Github Actions Build 에러 (0) 2024.03.15