带有基于Spring的SockJS/STOMP Web套接字的JSON Web令牌(JWT) [英] JSON Web Token (JWT) with Spring based SockJS / STOMP Web Socket
问题描述
我正在使用Spring Boot(1.3.0.BUILD-SNAPSHOT)设置一个RESTful Web应用程序,该应用程序包括一个STOMP/SockJS WebSocket,我打算从iOS应用程序和Web浏览器中使用它.我想使用 JSON Web令牌(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
注释的类,可以处理各种功能,并且通过在我的WebSecurityConfiguration
类中注册的JWTTokenFilter
成功地保护了这些位.
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.0 和会出现 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)?
推荐答案
Seems like support for a query string was added to the SockJS client, see https://github.com/sockjs/sockjs-client/issues/72.
这篇关于带有基于Spring的SockJS/STOMP Web套接字的JSON Web令牌(JWT)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!