簡體   English   中英

SpringMVC Websockets使用Spring Security進行消息傳遞用戶身份驗證

[英]SpringMVC Websockets Messaging User Authentication with Spring Security

我已經看到了關於這個問題的幾個主題,但它們似乎都沒有直接回答這個問題。

背景,我在應用程序的其他部分安裝了彈簧安全,工作和運行。 我的用戶名是“開發者”。

在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<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

    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

    <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

這是問題(如上所述):任何人都可以訂閱其他用戶的訂閱源。

現在,還有其他幾個版本,我將在下面列出它們,並解釋為什么答案都是錯誤的:

開放式websocket連接的安全問題是什么?

具有stomp安全性的Spring websocket - 每個用戶都可以訂閱任何其他用戶隊列?

Websocket:如何將消息推送給目標用戶

這是問題所在:

  • 查看messagingTemplate.convertAndSendToUser - 只需添加“用戶前綴”然后添加用戶名,然后使用不應用安全性的messagingTemplate.convertAndSend

  • 然后人們說“你需要像其他地方一樣使用Spring安全” - 這里的問題是A)我正在異步地向客戶端發送數據,所以B)我將完全在用戶會話之外使用這段代碼,可能來自不同的用戶(比如向另一個登錄用戶發送通知)。

讓我知道這是否與一個不同的帖子關系太密切,但我這對我來說是一個大問題,我想做到這一點。

如果有人需要更多細節,我可以獲得更多細節。

新的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的授權

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM