背景
我正在使用包含 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.0和 STOMP 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/