spring - JSON Web Token (JWT) 和基于 Spring 的 SockJS/STOMP Web Socket

标签 spring spring-security websocket jwt sockjs

背景

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

该应用程序受 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 配置是标准的:-
@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:-
@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用于处理各种功能的带注释的类,这些类通过 JWTTokenFilter 成功保护。在我的 WebSecurityConfiguration 中注册类(class)。

问题

但是我似乎无法使用 JWT 来保护 WebSocket。我正在使用 SockJS 1.1.0STOMP 1.7.1在浏览器中,无法弄清楚如何传递 token 。它would appear that SockJS 不允许使用初始 /info 发送参数和/或握手请求。

Spring Security for WebSockets documentation states AbstractSecurityWebSocketMessageBrokerConfigurer确保:

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



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

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

问题

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

最佳答案

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

关于spring - JSON Web Token (JWT) 和基于 Spring 的 SockJS/STOMP Web Socket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30887788/

相关文章:

spring - 分组/汇总 Spring 批处理记录

spring-security - 使用 Spring Security 的 SpEL 格式查询 Spring Data JPA

javascript - ng重复:dupes even with track by $index (special case)

javascript - 如何将 TogetherJS 用作聊天应用程序?

python - 没有名为 'websocket' 的模块

java - Spring 事务回滚

java - 根据系统环境变量加载Spring-Boot application.yaml文件

java - 无法解析字符串值中的占位符

spring - 在JSP页面中获取用户名。主体.用户名不起作用

Azure AD 无法与 spring-boot webflux 配合使用