2017-04-04 50 views
2

我加入了自定義的基於令牌的認證爲我的春天的Web應用程序,並延長了彈簧的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"); 

當t他認證令牌12345token用戶名是user1。但是,當我發送消息到user1,它沒有收到客戶端。有什麼我錯過了這個?

回答

2

在你的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); 
    } 
} 

在客戶端,用戶應訂閱話題/用戶/隊列/答覆。

還必須添加一些目的前綴:

@Configuration 
@EnableWebSocketMessageBroker 
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer { 

    @Override 
    public void configureMessageBroker(MessageBrokerRegistry config) { 
     config.enableSimpleBroker("/topic", "/queue" ,"/user"); 
     config.setApplicationDestinationPrefixes("/app"); 
     config.setUserDestinationPrefix("/user"); 
    } 
/*...*/ 
} 

當服務器收到關於/應用/你好隊列中的消息,應該將消息發送到您的DTO用戶。用戶必須與用戶的主體相同。

我認爲你的代碼唯一的問題是你的「/用戶」不在你的目標前綴。您的問候消息被阻止,因爲您將它們發送到以/ user開頭並且此前綴未註冊的隊列中。

你可以在git倉庫檢查來源: https://github.com/simvetanylen/test-spring-websocket

希望工程!

+1

看到的是,我希望郵件只發送給特定的用戶。如果我使用@SendTo(「/ user/queue/greetings」),那麼應用程序將知道我想向哪個用戶發送消息。我也嘗試了你的建議,但沒有收到客戶端的任何通知。 – BiJ

+0

我已經這樣做了。我會盡力找到我的代碼並將其發佈到此處。 –

+0

這將是一個很大的幫助。 – BiJ

0

在我之前的項目中,我向一個特定用戶發送了消息;詳細我寫了下面:

客戶端

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

我希望它很有用

+0

謝謝。我今天會嘗試一下,讓你知道。只有一個問題很難說如何使用'AbstractWebSocketMessageBrokerConfigurer'來配置這個套接字 – BiJ