Search code examples
spring-websocket

Spring WebSocket. Get access to Cookie in Config


I'm trying to configure WebSocket via Spring with STOMP, OAuth 2 and SockJS. New spec tells us how to implement it using Interceptors. The case is: if user is authenticated there is an Bearer Token in Native header of CONNECT request and there is no problem to set principal via Token. But my task is to use BrowserToken for unauthorized users (which is saved in Cookies). How can i get it from the request?


Solution

  • I've found a solution:

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/websocket/tracker")
            .withSockJS()
            .setInterceptors(httpSessionHandshakeInterceptor());
    }
    @Bean
    public HandshakeInterceptor httpSessionHandshakeInterceptor() {
        return new HandshakeInterceptor() {
            @Override
            public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Map<String, Object> attributes) throws Exception {
                if (request instanceof ServletServerHttpRequest) {
                    ServletServerHttpRequest servletServerRequest = (ServletServerHttpRequest) request;
                    HttpServletRequest servletRequest = servletServerRequest.getServletRequest();
                    Cookie token = WebUtils.getCookie(servletRequest, "key");
                    attributes.put("token", token.getValue());
                }
                return true;
            }
            @Override
            public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler, Exception exception) {
            }
        };
    }
    

    And finally

    @Override
    public void configureClientInboundChannel(ChannelRegistration registration) {
        registration.setInterceptors(new ChannelInterceptorAdapter() {
            @Override
            public Message<?> preSend(Message<?> message, MessageChannel channel) {
                StompHeaderAccessor accessor =
                    MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
                if (StompCommand.CONNECT.equals(accessor.getCommand())) {
                    Map<String, Object> sessionAttributes = accessor.getSessionAttributes();
                    List<String> authorization = accessor.getNativeHeader("Authorization");
                    Principal user = ... ; // get Principal using authentication / browser token
                    accessor.setUser(user);
                }
    
                return message;
            }
        });
    }