복붙노트

[SPRING] Spring에서 STOMP 및 WebSocket을 사용하여 특정 사용자에게 메시지를 보내는 동안 인증 확인

SPRING

Spring에서 STOMP 및 WebSocket을 사용하여 특정 사용자에게 메시지를 보내는 동안 인증 확인

저는 Build-in Message Broker와 WebSocket을 통한 STOMP를 사용하여 Spring 4에서 실시간 알림 시스템을 개발하고 있습니다.

사용자 이름에 따라 특정 사용자에게 메시지를 보내고 싶습니다. 이 목표를 달성하기 위해 다음과 같이 org.springframework.messaging.simp.SimpMessagingTemplate 클래스의 convertAndSendToUser 메소드를 사용하고 있습니다.

private final MessagingTemplate messagingTemplate;

@Autowired
public LRTStatusListener(SimpMessagingTemplate messagingTemplate) {
    this.messagingTemplate = messagingTemplate;
}


@Scheduled(fixedDelay=5000)
public void sendMessages(Principal principal)
    messagingTemplate
        .convertAndSendToUser(principal.getName(), "/horray", "Horray, " + principal.getName() + "!");
}

구성 :

@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/notifications").withSockJS();
    }

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic", "/queue", "/user");
    }

}

클라이언트 측 (자바 스크립트를 통해)에서는 사용자 이름을 지정하여 채널을 구독해야합니다 (아주 비슷한 다른 질문 인 : Spring Websocket의 특정 사용자에게 메시지 보내기).

stompClient.subscribe('/user/' + username + '/horray, ...) 

이 마지막 지점은 이상하게 들린다.

구독하여 webapp에 w.white로 로그인했다고 가정합니다.

stompClient.subscribe('/user/w.white/horray, ...)

... 나는 w.white에게 보낸 메시지를 볼 수있게 될 것입니다. 그리고 이것은 대단합니다 ... 그러나 구독하기 :

stompClient.subscribe('/user/j.pinkman/horray, ...)

... j.pinkman에게 보낸 메시지도 볼 수 있으며, 현재 w.white로 기록되어 있습니다.

이 문제를 극복하는 방법입니까?

아래에는 WebSocket을 통한 연결에 대한 로그가 있습니다.

Opening Web Socket... 
Web Socket Opened... 
>>> CONNECT
accept-version:1.1,1.0
heart-beat:10000,10000

<<< CONNECTED
user-name:w.white
heart-beat:0,0
version:1.1

connected to server undefined
Connected: CONNECTED
version:1.1
heart-beat:0,0
user-name:w.white

>>> SUBSCRIBE
id:sub-0
destination:/topic/lrt

>>> SUBSCRIBE
id:sub-1
destination:/user/lrt

해결법

  1. ==============================

    1.해결책을 찾았습니다.

    해결책을 찾았습니다.

    먼저, / 사용자 채널은 이미 Spring STOMP에 의해 관리되고 있음을 알아야하며, 등록은 필요 없습니다.

    그래서:

    @Override
    public void configureMessageBroker(MessageBrokerRegistry registry) {
        registry.enableSimpleBroker("/topic", "/queue");
    }
    

    그런 다음 대상 채널을 / queue / horray로 설정했습니다.

    @Scheduled(fixedDelay=5000)
    public void sendMessages(Principal principal)
        messagingTemplate
            .convertAndSendToUser(principal.getName(), "/queue/horray", "Horray, " + principal.getName() + "!");
    }
    

    마침내 클라이언트에서 :

    stompClient.subscribe('/user/queue/horray', '...');
    

    자, 잘 작동합니다! 보안 컨텍스트에서 가져온 Principal에 따라 메시지가 지정된받는 사람에게만 보내집니다.

  2. ==============================

    2.애플리케이션의 사용자가 인증되지 않았기 때문에 세션 ID를 사용하여 다양한 주제를 구분했습니다.

    애플리케이션의 사용자가 인증되지 않았기 때문에 세션 ID를 사용하여 다양한 주제를 구분했습니다.

    서버에서 :

    template.convertAndSend("/topic/warnings/" + sessionId, ...)
    

    그리고 고객은 꽤 간단합니다.

    stompClient.subscribe('/topic/warnings/${pageContext.session.id}', ...
    

    어쩌면 가장 깨끗한 방법은 아니지만 작동하지만 인증 없이는 / 사용자 채널을 사용할 수 없습니다.

  3. from https://stackoverflow.com/questions/25646671/check-auth-while-sending-a-message-to-a-specific-user-by-using-stomp-and-websock by cc-by-sa and MIT license