JSON Web Token (JWT) 和基于 Spring 的 SockJS/STOMP Web Socket [英] JSON Web Token (JWT) with Spring based SockJS / STOMP Web Socket

查看:25
本文介绍了JSON Web Token (JWT) 和基于 Spring 的 SockJS/STOMP Web Socket的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用包含 STOMP/SockJS WebSocket 的 Spring Boot (1.3.0.BUILD-SNAPSHOT) 设置 RESTful Web 应用程序,我打算从 iOS 应用程序和 Web 浏览器使用它.我想使用 JSON Web Tokens (JWT) 来保护 REST 请求和 WebSocket 接口,但我在使用后者时遇到困难.

I am in the process of setting up a RESTful web application using Spring Boot (1.3.0.BUILD-SNAPSHOT) that includes a STOMP/SockJS WebSocket, which I intend to consume from an iOS app as well as web browsers. I want to use JSON Web Tokens (JWT) to secure the REST requests and the WebSocket interface but I’m having difficulty with the latter.

该应用程序受 Spring Security 保护:-

The app is secured with Spring Security:-

@Configuration
@EnableWebSecurity
public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter {

    public WebSecurityConfiguration() {
        super(true);
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication()
                .withUser("steve").password("steve").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .exceptionHandling().and()
            .anonymous().and()
            .servletApi().and()
            .headers().cacheControl().and().and()

            // Relax CSRF on the WebSocket due to needing direct access from apps
            .csrf().ignoringAntMatchers("/ws/**").and()

            .authorizeRequests()

            //allow anonymous resource requests
            .antMatchers("/", "/index.html").permitAll()
            .antMatchers("/resources/**").permitAll()

            //allow anonymous POSTs to JWT
            .antMatchers(HttpMethod.POST, "/rest/jwt/token").permitAll()

            // Allow anonymous access to websocket 
            .antMatchers("/ws/**").permitAll()

            //all other request need to be authenticated
            .anyRequest().hasRole("USER").and()

            // Custom authentication on requests to /rest/jwt/token
            .addFilterBefore(new JWTLoginFilter("/rest/jwt/token", authenticationManagerBean()), UsernamePasswordAuthenticationFilter.class)

            // Custom JWT based authentication
            .addFilterBefore(new JWTTokenFilter(), UsernamePasswordAuthenticationFilter.class);
    }

}

WebSocket 配置是标准的:-

The WebSocket configuration is standard:-

@Configuration
@EnableScheduling
@EnableWebSocketMessageBroker
public class WebSocketConfiguration extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

    @Override
    public void registerStompEndpoints(StompEndpointRegistry registry) {
        registry.addEndpoint("/ws").withSockJS();
    }

}

我还有一个 AbstractSecurityWebSocketMessageBrokerConfigurer 的子类来保护 WebSocket:-

I also have a subclass of AbstractSecurityWebSocketMessageBrokerConfigurer to secure the WebSocket:-

@Configuration
public class WebSocketSecurityConfiguration extends AbstractSecurityWebSocketMessageBrokerConfigurer {

    @Override
    protected void configureInbound(MessageSecurityMetadataSourceRegistry messages) {
        messages.anyMessage().hasRole("USER");
    }

    @Override
    protected boolean sameOriginDisabled() {
        // We need to access this directly from apps, so can't do cross-site checks
        return true;
    }

}

还有几个 @RestController 注释类来处理各种功能,这些类通过在我的 WebSecurityConfigurationJWTTokenFilter 成功保护代码>类.

There is also a couple of @RestController annotated classes to handle various bits of functionality and these are secured successfully via the JWTTokenFilter registered in my WebSecurityConfiguration class.

但是我似乎无法使用 JWT 来保护 WebSocket.我正在使用 SockJS 1.1.0STOMP 1.7.1 在浏览器中,无法弄清楚如何传递令牌.看起来 SockJS 不允许使用初始 /info 发送参数代码>和/或握手请求.

However I can't seem to get the WebSocket to be secured with JWT. I am using SockJS 1.1.0 and STOMP 1.7.1 in the browser and can't figure out how to pass the token. It would appear that SockJS does not allow parameters to be sent with the initial /info and/or handshake requests.

Spring Security for WebSockets 文档说明AbstractSecurityWebSocketMessageBrokerConfigurer 确保:

任何入站 CONNECT 消息都需要有效的 CSRF 令牌来执行同源策略

Any inbound CONNECT message requires a valid CSRF token to enforce Same Origin Policy

这似乎意味着初始握手应该是不安全的,并且在接收到 STOMP CONNECT 消息时调用身份验证.不幸的是,我似乎无法找到任何有关实现这一点的信息.此外,这种方法需要额外的逻辑来断开打开 WebSocket 连接并且从不发送 STOMP CONNECT 的流氓客户端的连接.

Which seems to imply that the initial handshake should be unsecured and authentication invoked at the point of receiving a STOMP CONNECT message. Unfortunately I can't seem to find any information with regards to implementing this. Additionally this approach would require additional logic to disconnect a rogue client that opens a WebSocket connection and never sends a STOMP CONNECT.

作为(非常)新的 Spring 我也不确定 Spring Sessions 是否或如何适应这个.虽然文档非常详细,但似乎没有一个很好且简单(又名白痴)的指南来说明各种组件如何组合在一起/相互交互.

Being (very) new to Spring I'm also not sure if or how Spring Sessions fits into this. While the documentation is very detailed there doesn't appear to a nice and simple (aka idiots) guide to how the various components fit together / interact with each other.

我如何通过提供 JSON Web 令牌来保护 SockJS WebSocket,最好是在握手时(甚至可能)?

How do I go about securing the SockJS WebSocket by providing a JSON Web Token, preferably at the point of handshake (is it even possible)?

推荐答案

似乎 SockJS 客户端添加了对查询字符串的支持,参见 https://github.com/sockjs/sockjs-client/issues/72.

Seems like support for a query string was added to the SockJS client, see https://github.com/sockjs/sockjs-client/issues/72.

这篇关于JSON Web Token (JWT) 和基于 Spring 的 SockJS/STOMP Web Socket的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆