[SPRING] Spring websocket이 특정 사용자에게 전송
SPRINGSpring websocket이 특정 사용자에게 전송
내 봄 - 웹 응용 프로그램에 대한 사용자 지정 토큰 기반 인증을 추가하고 아래와 같이 스프링 websocket에 대해 동일한 확장
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic", "/queue");
config.setApplicationDestinationPrefixes("/app");
config.setUserDestinationPrefix("/user");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/gs-guide-websocket").setAllowedOrigins("*").withSockJS();
}
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new ChannelInterceptorAdapter() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor =
MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String jwtToken = accessor.getFirstNativeHeader("Auth-Token");
if (!StringUtils.isEmpty(jwtToken)) {
Authentication auth = tokenService.retrieveUserAuthToken(jwtToken);
SecurityContextHolder.getContext().setAuthentication(auth);
accessor.setUser(auth);
//for Auth-Token '12345token' the user name is 'user1' as auth.getName() returns 'user1'
}
}
return message;
}
});
}
}
소켓에 연결하는 클라이언트 측 코드는 다음과 같습니다.
var socket = new SockJS('http://localhost:8080/gs-guide-websocket');
stompClient = Stomp.over(socket);
stompClient.connect({'Auth-Token': '12345token'}, function (frame) {
stompClient.subscribe('/user/queue/greetings', function (greeting) {
alert(greeting.body);
});
});
그리고 내 컨트롤러에서 메시지를 보내고 있습니다.
messagingTemplate.convertAndSendToUser("user1", "/queue/greetings", "Hi User1");
인증 토큰 12345token의 경우 사용자 이름은 user1입니다. 그러나 user1에게 메시지를 보내면 클라이언트 쪽에서 수신되지 않습니다. 이것으로 내가 빠진 것이 있습니까?
해결법
-
==============================
1.Websocket 컨트롤러에서 다음과 같이해야합니다 :
Websocket 컨트롤러에서 다음과 같이해야합니다 :
@Controller public class GreetingController { @Autowired private SimpMessagingTemplate messagingTemplate; @MessageMapping("/hello") public void greeting(Principal principal, HelloMessage message) throws Exception { Greeting greeting = new Greeting(); greeting.setContent("Hello!"); messagingTemplate.convertAndSendToUser(message.getToUser(), "/queue/reply", greeting); } }
클라이언트 측에서는 사용자가 topic / user / queue / reply에 가입해야합니다.
또한 일부 착신 접두사를 추가해야합니다.
@Configuration @EnableWebSocketMessageBroker public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { @Override public void configureMessageBroker(MessageBrokerRegistry config) { config.enableSimpleBroker("/topic", "/queue" ,"/user"); config.setApplicationDestinationPrefixes("/app"); config.setUserDestinationPrefix("/user"); } /*...*/ }
서버가 / app / hello 대기열에서 메시지를 받으면 사용자의 dto에 메시지를 보내야합니다. 사용자는 사용자의 주체와 같아야합니다.
귀하의 코드에서 유일한 문제는 귀하의 "/ 사용자"가 목적지 접두사에 없다는 것입니다. 인사 메시지는 / user로 시작하는 대기열에서 메시지를 보냈으므로 차단되었습니다.이 접두사는 등록되지 않았습니다.
git repo에서 소스를 확인할 수 있습니다. https://github.com/simvetanylen/test-spring-websocket
희망 그것이 작동합니다!
-
==============================
2.이전 프로젝트에서는 특정 사용자에게 메시지를 보냈습니다. 나는 다음과 같이 썼다.
이전 프로젝트에서는 특정 사용자에게 메시지를 보냈습니다. 나는 다음과 같이 썼다.
고객 입장에서:
function stompConnect(notificationTmpl) { var socket = new SockJS('/comm-svr'); stompClient = Stomp.over(socket); var theUserId stompClient.connect({userId:theUserId}, function (frame) { debug('Connected: ' + frame); stompClient.subscribe('/topic/connect/'+theUserId, function (data) { //Handle data } }); }
서버 측
스프링 websocket 리스너 :
@Component public class WebSocketSessionListener { private static final Logger logger = LoggerFactory.getLogger(WebSocketSessionListener.class.getName()); private List<String> connectedClientId = new ArrayList<String>(); @EventListener public void connectionEstablished(SessionConnectedEvent sce) { MessageHeaders msgHeaders = sce.getMessage().getHeaders(); Principal princ = (Principal) msgHeaders.get("simpUser"); StompHeaderAccessor sha = StompHeaderAccessor.wrap(sce.getMessage()); List<String> nativeHeaders = sha.getNativeHeader("userId"); if( nativeHeaders != null ) { String userId = nativeHeaders.get(0); connectedClientId.add(userId); if( logger.isDebugEnabled() ) { logger.debug("Connessione websocket stabilita. ID Utente "+userId); } } else { String userId = princ.getName(); connectedClientId.add(userId); if( logger.isDebugEnabled() ) { logger.debug("Connessione websocket stabilita. ID Utente "+userId); } } } @EventListener public void webSockectDisconnect(SessionDisconnectEvent sde) { MessageHeaders msgHeaders = sde.getMessage().getHeaders(); Principal princ = (Principal) msgHeaders.get("simpUser"); StompHeaderAccessor sha = StompHeaderAccessor.wrap(sde.getMessage()); List<String> nativeHeaders = sha.getNativeHeader("userId"); if( nativeHeaders != null ) { String userId = nativeHeaders.get(0); connectedClientId.remove(userId); if( logger.isDebugEnabled() ) { logger.debug("Connessione websocket stabilita. ID Utente "+userId); } } else { String userId = princ.getName(); connectedClientId.remove(userId); if( logger.isDebugEnabled() ) { logger.debug("Connessione websocket stabilita. ID Utente "+userId); } } } public List<String> getConnectedClientId() { return connectedClientId; } public void setConnectedClientId(List<String> connectedClientId) { this.connectedClientId = connectedClientId; } }
봄 websocket 메시지 발신자 :
@Autowired private SimpMessagingTemplate msgTmp; private void propagateDvcMsg( WebDeviceStatusInfo device ) { String msg = ""; String userId =((Principal)SecurityContextHolder.getContext().getAuthentication().getPrincipal()).getName() msgTmp.convertAndSend("/topic/connect"+userId, msg); }
유용하게 사용되기를 바랍니다.
from https://stackoverflow.com/questions/43198292/spring-websocket-send-to-specific-people by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring 데이터 MongoDB Annotation @CreatedDate가 작동하지 않습니다. ID가 수동으로 할당 된 경우 (0) | 2019.03.30 |
---|---|
[SPRING] 교차 원산지 요청 차단 된 Spring REST 서비스 + AJAX (0) | 2019.03.30 |
[SPRING] Spring MVC에서 정적 페이지 주소 지정을 처리하는 방법 (0) | 2019.03.30 |
[SPRING] spring-mvc에서 페이지를 리디렉션하는 매개 변수를 전달하는 방법 (0) | 2019.03.30 |
[SPRING] Thymeleaf 템플릿에서 세션 속성에 액세스하기 (0) | 2019.03.30 |