0

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)?
Marc
  • 6,773
  • 10
  • 44
  • 68
  • I wonder if there is a scenario under which AbstractSessionWebSocketMessageBrokerConfigurer and webstomp-client can work together. At this point, I don't think so. – Marc Jun 13 '16 at 20:34

1 Answers1

1

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.

Rossen Stoyanchev
  • 4,910
  • 23
  • 26
  • Also you have seen the samples https://github.com/spring-projects/spring-session/tree/master/samples/websocket ? – Rossen Stoyanchev Jun 15 '16 at 16:08
  • I notice in one of your other posts that you're setting sessionCookieNeeded=false for your SockJS configuration. That could explain your issues, if the cookie that indicates you jsessionid isn't getting passed to the server. – Rossen Stoyanchev Jun 15 '16 at 16:16
  • Thanks for your insights. It could be my inexperience in this area, but didn't think I would be able to use cookies in a mobile app scenario. – Marc Jun 16 '16 at 00:47
  • I'm just not sure how to initialize the session since during the initial handshake stomp doesn't seem to allow any custom headers. So, I can't pass the SPRING.SESSION.ID there as a header (but it does allow them in subsequent messages). If it is indeed possible to pass a cookie, I could pass it like that. It's just that I'm not on a browser, so not sure how that works. But it offers a direction of exploration – Marc Jun 16 '16 at 01:00
  • Ok, you were right: I could initiate the session through the cookie! Great! So, now my second question is. What is the suggested solution for allowing the user to automatically login, remember me cookie? Funny, I fully expected the whole interaction to work through headers. – Marc Jun 16 '16 at 01:43
  • Are you sure the /ws/websocket endpoint accepts and receives cookies? My cookies are passed through nginx I see them coming in when I hit the /login endpoint, but not when I hit the websocket CONNECT endpoint – Marc Jun 17 '16 at 14:14
  • The endpoint is just another HTTP URL that hits the Servlet container. I really don't understand your question. There is no magic here. – Rossen Stoyanchev Jun 17 '16 at 18:35
  • Ok, thx. I will consider this a answered and post any additional questions separately. – Marc Jun 18 '16 at 16:52