JWT 필터로 유저를 검증하고 유저 정보를 추출했었는데 STOMP는 HTTP 위에서 동작하는 것이 아니기 때문에 HTTP 헤더를 받아올 수 없었음.

Untitled

→ STOMP 메세지 보낼 때 headers 옵션을 추가하고 JWT를 보낸 후 컨트롤러에서 @Header 어노테이션을 통해 헤더 수신. 이후 서비스에서 JWT로 유저 정보 추출

Untitled

Untitled

function sendMessage() {
    const content = messageInput.val();
    stompClient.publish({
        destination: `/app/chat-rooms/${currentRoomId}/messages`,
        headers: {Authorization: getToken()},
        body: JSON.stringify({'content': content})
    });
    messageInput.val("");
}

@MessageMapping("/chat-rooms/{roomId}/messages")
@SendTo("/topic/chat-rooms/{roomId}")
public GetMessageResponse sendMessage(
	@DestinationVariable Long roomId,
  CreateMessageRequest request,
  @Header("Authorization") String token
) throws Exception {
	Thread.sleep(500); // 지연 시뮬레이션

  return messageService.createMessage(roomId, request, token);
}

하지만 기존에 필터에서 처리되는 검증 작업이 이루어지지 않았고 해당 검증을 서비스에서 전부 처리하기엔 유지보수적인 측면에서 안 좋다고 판단함.

STOMP에도 필터와 비슷한 역할을 하는 Interceptor를 알게 됐고 이를 통해 해결

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.interceptors(new ChannelInterceptor() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) {
                StompHeaderAccessor headerAccessor = MessageHeaderAccessor.getAccessor(message,
                    StompHeaderAccessor.class);

                if (headerAccessor != null && headerAccessor.getCommand() == StompCommand.SEND) {
                    String token = headerAccessor.getFirstNativeHeader("Authorization");

                    if (token != null) {
                        jwtUtil.validateToken(token);
                    }
                }

                return message;
            }
        });
    }

Untitled