Search code examples
spring-websocketspring-session

Not getting SPRING.SESSION.ID from headers


I'm using spring session and AbstractSessionWebSocketMessageBrokerConfigurer and am trying to create a STOMP Websocket with support for Spring Security and Spring Session. I can't seem to get my session activated. I use webstomp-client to connect (https://github.com/JSteunou/webstomp-client)

AbstractSessionWebSocketMessageBrokerConfigurer creates

@Bean
@SuppressWarnings("unchecked")
public SessionRepositoryMessageInterceptor<S> sessionRepositoryInterceptor() {
    return new SessionRepositoryMessageInterceptor<S>(this.sessionRepository);
}

I pass as header to both the connect event and every message

SPRING.SESSION.ID:<My session id>

When I check the processing in SessionRepositoryMessageInterceptor, I see that it is trying to retrieve the session id through SimpMessageHeaderAccessor that expects the header to contain an object under header key simpSessionAttributes.

Map<String, Object> sessionHeaders = SimpMessageHeaderAccessor
            .getSessionAttributes(message.getHeaders());
    String sessionId = sessionHeaders == null ? null
            : (String) sessionHeaders.get(SPRING_SESSION_ID_ATTR_NAME);

All the attributes that SimpMessageHeaderAccessor seems to expect are not present in the stomp client and just seem to belong to a different protocol.

How do I deal with activating a session under Stomp, Spring WebSocket, Spring Security and Spring Session? Or more specifically:

  • Why does SessionRepositoryMessageInterceptor use SimpleHeaderAccessor in stead of StompHeaderAcessor?
  • What headers do I need to pass from a javascript client to create a session (assuming I received the session id through traditional login)?

Solution

  • I don't know what the issue is but I can explain a few things to help you debug the issue.

    Spring supports WebSocket-scoped attributes. Those are attributes that exist for as long as the session exists. The SessionRepositoryMessageInterceptor, as a HandshakeInterceptor, hooks into the initial HTTP handshake request and saves the SPRING.SESSION.ID as a WebSocket-scoped attribute. Then after the handshake, when STOMP messages start to flow, it intercepts every incoming message, and retrieves the SPRING.SESSION.ID in the websocket attributes. So I am not sure why you're trying to pass SPRING.SESSION.ID as a header. That's all managed for you as I just explained and associated with the WebSocket session.

    As for the question about SimpHeaderAccessor vs StompHeaderAcessor, the former is a more generalized version. It's not wrong to use it as long it gives you enough information. In this case Spring Session doesn't care for STOMP specific details.

    I don't understand your second question about what headers need to be passed from a javascript client to create a session. As long as the HTTP handshake is made within the same HTTP session it should just work. There is nothing different here from how you would do any HTTP call.