SpringMVC Websockets使用Spring Security进行消息传递用户身份validation

我已经看到了关于这个问题的几个主题,但它们似乎都没有直接回答这个问题。

背景,我在应用程序的其他部分安装了弹簧安全,工作和运行。 我的用户名是“开发者”。

在Java 7,Glassfish 4,Spring 4上运行,并使用Angular + StompJS

我们在这里得到一些代码:

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秒发送一次东西:

 import org.springframework.messaging.simp.SimpMessagingTemplate; … @Autowired private SimpMessagingTemplate messagingTemplate; … @Scheduled(fixedDelay = 3000) public void sendStuff () { Map 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

  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

   javax.websocket javax.websocket-api 1.0   org.springframework spring-messaging 4.0.6.RELEASE   org.springframework spring-websocket 4.0.6.RELEASE  

这是有用的:

  1. 我可以在客户端和服务器之间来回产生奇妙的通信
  2. 它很快
  3. messagingTemplate.convertAndSendmessagingTemplate.convertAndSendToUser

这是问题(如上所述):任何人都可以订阅其他用户的订阅源。

现在,还有一些其他版本的浮动,我将在下面列出它们,并解释为什么答案都是错误的:

开放式websocket连接的安全问题是什么?

具有stomp安全性的Spring websocket – 每个用户都可以订阅任何其他用户队列?

Websocket:如何将消息推送给目标用户

这是问题所在:

  • 查看messagingTemplate.convertAndSendToUser – 只需添加“用户前缀”,然后添加提供的用户名,然后使用不应用安全性的messagingTemplate.convertAndSend

  • 然后人们说“你需要像其他地方一样使用Spring安全” – 这里的问题是A)我正在异步地向客户端发送数据,所以B)我将完全在用户会话之外使用这段代码,可能来自不同的用户(比如向另一个登录用户发送通知)。

让我知道这是否与一个不同的post关系太密切,但我这对我来说是一个大问题,我想做到这一点。

如果有人需要更多细节,我可以获得更多细节。

新的Spring Security 4x现在完全支持Web Socket,您可以参考预览Spring Security WebSocket Support链接

或SpringSecuritySupportWebSocket.html ,以防您需要完整的示例,

我想你必须做出这些改变:

1)您不能为“/ user”启用SimpleBroker,因为它是代理自动处理的特殊队列

2)如果服务器使用例如注释“@SendToUser(”/ queue / private“)”客户端必须订阅队列“/ user / queue / private”:你不能在队列中添加用户名,因为它是一个经纪人处理的透明操作

我确信这是正常的,因为我在我的设置中使用它。

我没有尝试过convertAndSendToUser()方法,但由于它的语义应该与注释相同,所以它也应该工作。

您可以在扩展AbstractSecurityWebSocketMessageBrokerConfigurer的JavaConfig类中覆盖configureInbound方法。

 @Override protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) { messages .nullDestMatcher().authenticated() 1 .simpSubscribeDestMatchers("/user/queue/errors").permitAll() 2 .simpDestMatchers("/app/**").hasRole("USER") 3 .simpSubscribeDestMatchers("/user/**", "/topic/friends/*").hasRole("USER") 4 .simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll() 5 .anyMessage().denyAll(); 6 } } 

在那里,您可以配置凭据以订阅频道,发送消息或其他一些内容,如Spring WebSocket documntation https://docs.spring.io/spring-security/site/docs/current/reference/html/websocket中所述。 HTML#WebSocket的授权