2
votes

I wrote a small project that uses Spring MVC 4 with Websockets and RabbitMQ as the broker. I am trying to send back to a single user (convertAndSendToUser) but I can't seem to have it working. Here is what the application does:

  1. authenticate to Spring Security over HTTP. The authentication is over AJAX and the backend assigns a UUID as the username to every new connection. There might be multiple clients with the same username so I would like to be able to target individual browsers although they may be logged in with the same username
  2. after authenticating over AJAX the webapp connects to the APIs using STOMP over Websockets. These are the headers that get send back in the CONNECT FRAME

    body: "" command: "CONNECTED" headers: Object heart-beat: "0,0" server: "RabbitMQ/3.3.1" session: "session-OGzAN6T8Y0X9ft3Jq04fiQ" user-name: "88dc9424-72e3-4814-be8c-e31dbf89b521" version: "1.1"

As you can see there is no frame-suffix or session-id field.

  1. When I use convertAndSendToUser from the backend, the response is send to a unique queue like: /exchange/jobs-userh6g_48h9. The queue name is /exchange/jobs but Spring automatically attaches the suffix -userh6g_48h9. The username is "user" and the sessionId is "h6g_48h9" This is fine and I want this behavior but the problem is that the client (webapp) doesn't get this session id in the CONNECT frame and there is no way for it to actually subscribe to that unique queue.

How to solve this? I want the queue-suffix/session id sent back to me on connect so that the client can get this suffix and subscribe to his unique queues. Currently no messages come back from the server because of this lack of information.

1

1 Answers

0
votes

Correct me if I'm wrong, but due to the UserDestinationMessageHandler, clients should be able to subscribe to /user/exchange/jobs and that message handler will correct the queue name for you.

As a side note, you should also consider adding a configuration class extending AbstractSecurityWebSocketMessageBrokerConfigurer similar to the following:

@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    @Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages
                .antMatchers(SimpMessageType.MESSAGE, "/topic/**", "/queue/**").denyAll() // Prevent users sending messages directly to topics and queues
                .antMatchers(SimpMessageType.SUBSCRIBE, "/queue/**/*-user*", "/topic/**/*-user*").denyAll() // Prevent users from subscriptions to private queues
                .antMatchers("/user/queue/errors").permitAll()
                .anyMessage().hasRole("ANY_OPTIONAL_ROLE_ETC")
        ;
    }
}

This will prevent "enterprising" users from subscribing to things that they shouldn't.