SpringMVC Websockets使用Spring Security进行消息传递用户身份验证
我已经看到了关于这个问题的几个主题,但是它们似乎都没有直接回答这个问题。
I have seen a couple of threads about this issue, but none of them seem to really answer the question directly.
背景,我安装了spring security,工作正常,并在应用程序的其他部分顺利运行。我的用户名是开发人员。
Background, I have spring security installed, working, and running smoothly in other parts of the application. My username is "developer".
在Java 7,Glassfish 4,Spring 4上运行,并使用Angular + StompJS
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);
}
}
好的,现在这里是一个控制器,每隔3秒发送一次东西:
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());
}
最后使用SockJS的JavaScript
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;
最后,对于踢,pom.xml
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>
以下是工作原理:
- 我可以在客户端和服务器之间来回交流。
- 快速
-
messagingTemplate.convertAndSend
和messagingTemplate.convertAndSendToUser
- 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:
Spring websocket with stomp securi ty - 每个用户都可以订阅任何其他用户队列吗?
问题在于:
-
查看
messagingTemplate.convertAndSendToUser
- 所有这一切都是添加用户前缀,然后添加提供的用户名,然后使用messagingTemplate.convertAndSend
,这不适用安全性。
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.
然后人们说你需要像其他地方一样使用Spring安全 - 这里的问题是A)我正在异步地向客户端发送数据,所以B)我将使用这个代码完全在用户会话之外,可能来自不同的用户(比如向另一个登录用户发送通知)。
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.
新的Spring Security 4x现在完全支持Web Socket,你可以参考链接预览Spring Security WebSocket支持
New Spring Security 4x now fully support Web Socket, you can refer the link Preview Spring Security WebSocket Support
或 SpringSecuritySupportWebSocket.html ,以防您需要完整的示例,
Or SpringSecuritySupportWebSocket.html in case you need a complete example,