서버에서 특정 사용자에게만 웹 소켓 메시지를 보내는 방법은 무엇입니까?
내 webapp에는 스프링 보안 설정이 있으며 websocket을 사용합니다. 서버에서 특정 사용자에게만 메시지를 보내려고하는 까다로운 문제가 발생했습니다 .
매뉴얼 을 읽은 나의 이해는 우리가 할 수있는 서버에서 나온 것입니다.
simpMessagingTemplate.convertAndSend("/user/{username}/reply", reply);
그리고 클라이언트 측에서 :
stompClient.subscribe('/user/reply', handler);
하지만 구독 콜백을 호출 할 수 없었습니다. 나는 많은 다른 길을 시도했지만 운이 없다.
/ topic / reply로 보내면 작동하지만 다른 연결된 사용자도 모두 수신합니다.
문제를 설명하기 위해 github에서이 작은 프로젝트를 만들었습니다 : https://github.com/gerrytan/wsproblem
재현 단계 :
1) 프로젝트 복제 및 빌드 (jdk 1.7 및 maven 3.1을 사용하고 있는지 확인)
$ git clone https://github.com/gerrytan/wsproblem.git
$ cd wsproblem
$ mvn jetty:run
2)로 이동하고 http://localhost:8080
bob / test 또는 jim / test를 사용하여 로그인합니다.
3) “사용자 별 메시지 요청”을 클릭합니다. 예상 : “안녕하세요 {username}”메시지가이 사용자에 대해서만 “나에게만 수신 됨”옆에 표시됨, 실제 : 아무것도 수신되지 않음
답변
아, client side no need to known about current user
서버가 대신 해줄 것입니다.
서버 측에서 다음 방법을 사용하여 사용자에게 메시지를 보냅니다.
simpMessagingTemplate.convertAndSendToUser(username, "/queue/reply", message);
참고 : 사용 queue
하지 않고 topic
항상 사용 queue
하는 SpringsendToUser
클라이언트 측
stompClient.subscribe("/user/queue/reply", handler);
설명
websocket 연결이 열려 있으면 Spring은 연결마다 할당 session id
하지 않고 HttpSession
할당합니다. 그리고 클라이언트가으로 시작하는 채널을 구독하면 ( /user/
예 🙂 /user/queue/reply
서버 인스턴스가 이름이 지정된 큐에 구독합니다.queue/reply-user[session id]
사용하는 사용자, 예를 들어 메시지를 보낼 때 : 사용자 이름은 admin
당신이 쓸 것simpMessagingTemplate.convertAndSendToUser("admin", "/queue/reply", message);
Spring은 session id
사용자에게 매핑 된 것을 결정할 것 admin
입니다. 예 : 그것은 두 개의 세션을 발견 wsxedc123
하고 thnujm456
봄이 목적지로 변환합니다, queue/reply-userwsxedc123
그리고 queue/reply-userthnujm456
, 그것은 당신의 메시지 브로커 2 개 목적지로 메시지를 보낼 수 있습니다.
메시지 브로커는 메시지를 수신하고 각 세션에 해당하는 세션을 보유하는 서버 인스턴스에 다시 제공합니다 (WebSocket 세션은 하나 이상의 서버에서 보유 할 수 있음). Spring은 메시지를 destination
(예 🙂 user/queue/reply
및 session id
(예 :)로 번역합니다 wsxedc123
. 그런 다음 해당 메시지를Websocket session
답변
아 내 문제가 뭔지 찾았 어. 먼저 /user
간단한 브로커에 접두사를 등록하지 않았습니다.
<websocket:simple-broker prefix="/topic,/user" />
그러면 /user
보낼 때 추가 접두사 가 필요하지 않습니다 .
convertAndSendToUser(principal.getName(), "/reply", reply);
Spring은 자동으로 "/user/" + principal.getName()
목적지 앞에 추가 되므로 “/ user / bob / reply”로 해석됩니다.
이것은 또한 자바 스크립트에서 사용자마다 다른 주소를 구독해야 함을 의미합니다.
stompClient.subscribe('/user/' + userName + '/reply,...)
답변
STOMP를 사용하여 샘플 웹 소켓 프로젝트도 만들었습니다. 내가 알아 차린 것은
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue");// including /user also works
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/getfeeds").withSockJS();
}
}
“/ user”가 config.enableSimpleBroker (…
답변
Thanh Nguyen Van의 최선의 설명을 기반으로 한 내 솔루션이지만 MessageBrokerRegistry를 구성했습니다.
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/queue/", "/topic/");
...
}
...
}
답변
정확히 나는 똑같이했고 사용자를 사용하지 않고 작동합니다.
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/gs-guide-websocket").withSockJS();
}
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic" , "/queue");
config.setApplicationDestinationPrefixes("/app");
}
}