I have seen a couple of threads about this issue, but none of them seem to really answer the question directly.
Background, I have spring security installed, working, and running smoothly in other parts of the application. My username is "developer".
Running on Java 7, Glassfish 4, Spring 4, and using Angular + StompJS
Let's get some code here:
package com.myapp.config; import org.springframework.context.annotation.Configuration; import org.springframework.messaging.simp.config.MessageBrokerRegistry; import org.springframework.web.socket.config.annotation.AbstractWebSocketMessageBrokerConfigurer; import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker; import org.springframework.web.socket.config.annotation.StompEndpointRegistry; @Configuration @EnableWebSocketMessageBroker public class WebSocketBrokerConfig extends AbstractWebSocketMessageBrokerConfigurer { public final static String userDestinationPrefix = "/user/"; @Override public void registerStompEndpoints(StompEndpointRegistry registry) { registry.addEndpoint("/stomp").withSockJS().setSessionCookieNeeded(true); } @Override public void configureMessageBroker(MessageBrokerRegistry registry) { registry.setApplicationDestinationPrefixes("/app"); //registry.enableStompBrokerRelay("/topic,/user"); registry.enableSimpleBroker("/topic", "/user"); registry.setUserDestinationPrefix(userDestinationPrefix); } }
Ok, now here is a controller, to send out stuff every 3 seconds:
import org.springframework.messaging.simp.SimpMessagingTemplate; … @Autowired private SimpMessagingTemplate messagingTemplate; … @Scheduled(fixedDelay = 3000) public void sendStuff () { Map<String, Object> map = new HashMap<>(); map.put(MessageHeaders.CONTENT_TYPE, MimeTypeUtils.APPLICATION_JSON); System.out.print("Sending data! " + System.currentTimeMillis()); //messagingTemplate.convertAndSend("/topic/notify", "Public: " + System.currentTimeMillis()); messagingTemplate.convertAndSendToUser("developer", "/notify", "User: " + System.currentTimeMillis()); messagingTemplate.convertAndSendToUser("notYou", "/notify", "Mr Developer Should Not See This: " + System.currentTimeMillis()); }
And finally the JavaScript using SockJS
var client = new SockJS('/stomp'); var stomp = Stomp.over(client); stomp.connect({}, function(s) { //This should work stomp.subscribe('/user/' + s.headers['user-name'] + '/notify', console.debug); //This SHOULD NOT stomp.subscribe('/user/notYou/notify', console.debug); }); client.onclose = $scope.reconnect;
And finally, for kicks, the pom.xml
<dependency> <groupId>javax.websocket</groupId> <artifactId>javax.websocket-api</artifactId> <version>1.0</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-messaging</artifactId> <version>4.0.6.RELEASE</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-websocket</artifactId> <version>4.0.6.RELEASE</version> </dependency>
Here is what does work:
- I can produce wonderfully communication back and forth between the client and the server
- It's fast
messagingTemplate.convertAndSend
andmessagingTemplate.convertAndSendToUser
This is the problem (noted above): Anyone can subscribe to other users feeds.
Now, there are a few other versions of this floating around, I will list them below, and explain why the answers are all wrong:
What are the security issues around an open websocket connection?
Spring websocket with stomp security - every user can subscribe to any other users queue?
Websocket: How To Push A Message To A Target User
Here's the problem:
-
Look at
messagingTemplate.convertAndSendToUser
- All that does is add the "user prefix" and then the username provided and then usemessagingTemplate.convertAndSend
which does not apply security. -
Then people say that "you need to use spring security just like everywhere else" - the problem here is A) that I am SENDING data to the client asynchronously, so B) I will be using this code completely outside of the user's session, possibly from a different user (say to send a notification to another logged in user).
Let me know if this is too closely related to a different post, but I this is a big problem for me and I wanted to do this justice.
I can get more details though if anyone needs more details.