Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 871
Tolledo Avatar asked Dec 08 '22 20:12

Tolledo


1 Answers

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;
        }
    });
}
like image 57
Tolledo Avatar answered Jan 14 '23 07:01

Tolledo