您的位置:首页 > 编程语言 > Java开发

SpringMVC Websockets Messaging User Authentication with Spring Security

2014-10-23 14:46 1061 查看

1down
votefavorite
1

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
and
messagingTemplate.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 use
messagingTemplate.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.

javaspring

spring-mvc
spring-security
websocket
share|improve
this question
asked
Jul 28 at 20:47




Nitroware
580722

 
 
add a comment | 

1 Answer 1

activeoldestvotes

up vote2down vote
I think you must make these changes:

1) You must not enableSimpleBroker for "/user" because it's a special queue handled automatically by the broker

2) if the server uses for example the annotation "@SendToUser("/queue/private")" the client must subscribe to the queue "/user/queue/private" : you must not prepend the username in the queue because it's a transparent operation handled by the broker

I'm sure this works correctly because I'm using it in my setup.

I've not tried with the convertAndSendToUser() method but since its semantic should be the same of the annotation, it should work too.

share|improve
this answer
answered
Jul 29 at 17:22




Alessandro Polverini
838

 
 
Great response, thanks so much! I will go ahead and try that now and update you/mark it as solves as soon as I know. – Nitroware
Jul
29 at 17:31
1 
So I tried doing exactly what you had recommended and still it did not work. The critical problem here between our two situations is this: You are using
@SendToUser
which
already has the current users session and scope, and likely the user session. I am trying to send notifications, possibly from another, to a different user using
convertAndSendToUser()
which is where i am getting my problems from – Nitroware
Jul
29 at 18:55

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐