3

I want to use websocket in spring application for contact requests. I already have setup login page for users and I use spring security for that. My problem is following: how to securely send web socket messages to two different users.

I know that i can broadcast messages to every user subscribed to some topic with @SendTo() and can broadcast message to one user only with something like

messagingTemplate
    .convertAndSendToUser(principal.getName(), "/queue/requests", request);

because his username is stored in principal.

My problem is how to handle when we have to target 2 users from a request and make it secure so that you cant just listen to any channels from client side without being authorized.

Ideally I'm looking for something like

messagingTemplate
    .convertAndSendToUser(request.getFromUser(), "/queue/requests", request) 

messagingTemplate
    .convertAndSendToUser(request.getToUser(), "/queue/requests", request)
Bojan Trajkovski
  • 1,056
  • 1
  • 15
  • 31
  • I think you need Spring Security 4 for this, and Spring Boot uses Spring Security 3..."Spring Security 4.0 has introduced authorization support for WebSockets" – Neil McGuigan Oct 26 '15 at 21:48

2 Answers2

1

Spring WebSocket handles /user channel, so I used those methods

This is how I solved this problem:

When user authenticates with Spring Security, WebSocket module creates unique channel for that user based on his Principal. Example "/user/queue/position-updates" is translated to "/queue/position-updates-user123"

So on the client side all I had to do, was subscribe to /user/queue/requests

And on the server side, send messages to /user/{username}/queue/requests with convertAndSendToUser(request.getFromUser(), "/queue/requests", request) and Spring handles the rest.

Bojan Trajkovski
  • 1,056
  • 1
  • 15
  • 31
0

You can do something as follows given in Spring-websocket-chat. At client side you can have /app/chat.private.{targetUser}

At Server side you can get target user by using @DestinationVariable and source user from Principal

@MessageMapping("/chat.private.{username}")
    public void filterPrivateMessage(@Payload ChatMessage message, @DestinationVariable("username") String username, Principal principal) {
        checkProfanityAndSanitize(message);

        message.setUsername(principal.getName());

        simpMessagingTemplate.convertAndSend("/user/" + username + "/queue/chat.message", message);
    }
MasterCode
  • 975
  • 5
  • 21
  • 44