Spring websocket发送给特定的人

我为spring-web app添加了基于自定义令牌的身份validation,并为spring websocket扩展了相同的身份validation,如下所示

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"); 

对于auth令牌12345token ,用户名是user1 。 但是当我向user1发送消息时,它没有在客户端收到。 这有什么我想念的吗?

在您的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”不在您的目标前缀中。 您的问候消息被阻止,因为您将它们发送到以/ user开头的队列中,并且未注册此前缀。

您可以在git repo上查看来源: https : //github.com/simvetanylen/test-spring-websocket

希望它有效!

在我之前的项目中,我向一个特定用户发送了消息; 详细我写了以下内容:

客户端

 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 } }); } 

服务器端

Spring websocket听众:

 @Component public class WebSocketSessionListener { private static final Logger logger = LoggerFactory.getLogger(WebSocketSessionListener.class.getName()); private List connectedClientId = new ArrayList(); @EventListener public void connectionEstablished(SessionConnectedEvent sce) { MessageHeaders msgHeaders = sce.getMessage().getHeaders(); Principal princ = (Principal) msgHeaders.get("simpUser"); StompHeaderAccessor sha = StompHeaderAccessor.wrap(sce.getMessage()); List 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 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 getConnectedClientId() { return connectedClientId; } public void setConnectedClientId(List connectedClientId) { this.connectedClientId = connectedClientId; } } 

Spring 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); } 

我希望它有用