SpringMVC Websockets Messaging-Benutzerauthentifizierung mit Spring Security
Ich habe ein paar Threads zu diesem Thema gesehen, aber keiner von ihnen scheint die Frage wirklich direkt zu beantworten.
Hintergrund: In anderen Teilen der Anwendung ist Spring Security installiert, funktioniert und funktioniert einwandfrei. Mein Benutzername ist "Entwickler".
Läuft unter Java 7, Glassfish 4, Spring 4 und mit Angular + StompJS
Holen wir uns hier einen Code:
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, hier ist ein Controller, der alle 3 Sekunden etwas sendet:
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());
}
Und zum Schluss das JavaScript mit 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;
Und zum Schluss die 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>
Hier ist was funktioniert:
Ich kann wunderbar zwischen Client und Server hin und her kommunizierenEs ist schnellmessagingTemplate.convertAndSend
undmessagingTemplate.convertAndSendToUser
Dies ist das Problem (siehe oben): Jeder kann Feeds anderer Benutzer abonnieren.
Nun, es gibt ein paar andere Versionen davon, ich werde sie unten auflisten und erklären, warum die Antworten alle falsch sind:
Was sind die Sicherheitsprobleme bei einer offenen Websocket-Verbindung?
Websocket: So senden Sie eine Nachricht an einen Zielbenutzer
Hier ist das Problem:
AnsehenmessagingTemplate.convertAndSendToUser
- Fügen Sie lediglich das "Benutzerpräfix" und anschließend den angegebenen Benutzernamen hinzu und verwenden Sie dannmessagingTemplate.convertAndSend
das gilt nicht Sicherheit.
Dann sagen die Leute, dass "Sie Spring Security wie überall sonst verwenden müssen" - das Problem ist hier A) dass ich Daten asynchron an den Client sende, also B) dass ich diesen Code möglicherweise vollständig außerhalb der Sitzung des Benutzers verwende von einem anderen Benutzer (z. B. um eine Benachrichtigung an einen anderen angemeldeten Benutzer zu senden).
Lassen Sie mich wissen, ob dies zu eng mit einem anderen Beitrag zusammenhängt, aber ich habe ein großes Problem damit und wollte dem gerecht werden.
Ich kann jedoch mehr Details erfahren, wenn jemand mehr Details benötigt.