本文介绍了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>

以下是有效的:

  1. 我可以在客户端和服务器之间产生奇妙的来回通信
  2. 速度很快
  3. messagingTemplate.convertAndSendmessagingTemplate.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:

开放网络套接字有哪些安全问题连接?

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

Websocket:如何推送给目标用户的信息

问题来了:

  • 看看 messagingTemplate.convertAndSendToUser - 所做的就是添加用户前缀",然后是提供的用户名,然后使用 messagingTemplate.convertAndSend应用安全性.

  • 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.

然后人们说你需要像其他任何地方一样使用 spring security"——这里的问题是 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.

推荐答案

New 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,

这篇关于SpringMVC Websockets 消息传递用户身份验证与 Spring Security的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-01 19:14