Reputation: 602
I am implementing a Spring Boot + WebSocket + SockJS application and have a doubt about how to handle the HTTP session/ Websocket relation.
Basically I would like to be able to inform the user that his session has been invalidated (because of a timeout or because of having logged in from another location). For that I wanted to put in his own socket a certain message just before the framework closes it.
I turned to an http listener but the problem I have is that by the time HttpSessionListener.sessionDestroyed()
is called I can see the socket has been already closed by the framework (not due to some other event like the user closing the browser).
Has anybody any idea about how to achieve this?
I have a really simple Websocket config and am running with Spring Boot defaults.
@Configuration
@EnableWebSocketMessageBroker
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void configureWebSocketTransport(WebSocketTransportRegistration registration) {
registration.setMessageSizeLimit(10000000);
}
@Override
public void configureMessageBroker(MessageBrokerRegistry registry) {
registry.setApplicationDestinationPrefixes("/app/");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/myEndPoint").withSockJS();
}
}
Security part:
@Configuration
public class WebSocketSecurityConfig extends AbstractSecurityWebSocketMessageBrokerConfigurer {
@Override
protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
applySecurity(messages);
}
@Override
protected boolean sameOriginDisabled() {
return true;
}
private static void applySecurity(MessageSecurityMetadataSourceRegistry messages) {
messages.nullDestMatcher().authenticated() //
.simpDestMatchers("/app/**").authenticated().simpSubscribeDestMatchers("/user/reply").authenticated()
.simpTypeMatchers(MESSAGE, SUBSCRIBE).denyAll().anyMessage().denyAll();
}
}
My Http listener would be like this:
return new HttpSessionListener() {
@Override
public void sessionDestroyed(HttpSessionEvent se) {
simpMessagingTemplate.convertAndSendToUser(....);
}
@Override
public void sessionCreated(HttpSessionEvent se) {
// no need to do anything when a session is created
}
};
UPDATE:
Spring-session handles issues like this one and many others.
Upvotes: 2
Views: 2630
Reputation: 30809
HttpSession
and Websocket
session are two different kind of sessions. HttpSession
is created when client accesses the url and completes Handshake whereas Websocket
session is created when client sends subscribe request.
Websocket
session is wrapped under HttpSession
. If HttpSession
gets timed out or invalidated then underlying Websocket
session also gets disconnected, however, vice versa is not true.
Coming to your point of configuring listener for Websocket
session, HttpSession
listener won't be able to listen for Websocket
session events. For such events, we need to define a class which extends org.springframework.web.socket.messaging.SubProtocolWebSocketHandler
class and override afterConnectionEstablished
and afterConnectionClosed
methods. Have a look at Javadoc here.
Also, here is an example that listens for Spring websocket disconnect events. You need to configure something similar to this.
Upvotes: 2
Reputation: 310850
An HTTP session is supposed to survive the connection. That's what it's for. Multiple connections, same session. The session should not expire while there are active connections.
Upvotes: 0