获取Spring Boot 1.4 + Spring 4.x + Spring Security 4.x使用基于无状态令牌的身份验证的WebSocket身份验证似乎是一次冒险!
到目前为止,据我所知,SockJS无法使用令牌设置Authentication
标头,因为浏览器不会将该API暴露给Javascript(请参阅https://github.com/sockjs/sockjs-client/issues/196)。我已经解决了这个问题,方法是在查询参数中按照上述问题的建议设置身份验证令牌,然后使用带有HandshakeHandler
的Spring determineUser()
将查询参数映射到User实体。丑陋且不太安全,但至少它适用于WebSockets。
然而,当SockJS回归到另一种机制时,例如XHR流媒体,相同的机制不再有效。 HandshakeInterceptor
可以访问请求并可以从查询参数获取身份验证,但determineUser
上的 HandshakeHandler
永远不会被调用非WebSocket握手。
我到目前为止最接近的是绕过内置的连接级Spring机制来确定身份验证。相反,我通过在客户端的Stomp标头中设置身份验证令牌来设置消息级别,例如:
stompClient.send("/wherever", {token: 'token'}, ...);
并使用通道拦截器在服务器端提取它:
configureClientInboundChannel(ChannelRegistration registration) {
registration.setInterceptors(new ChannelInterceptorAdapter() {
Message<*> preSend(Message<*> message, MessageChannel channel) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
// not documented anywhere but necessary otherwise NPE in StompSubProtocolHandler!
accessor.setLeaveMutable(true);
List tokenList = accessor.getNativeHeader("token");
if(tokenList == null || tokenList.size < 1) {
return message;
}
Principal yourAuth = [...];
return MessageBuilder.createMessage(message.payload, accessor.messageHeaders)
}
})
现在Spring将Principal
注入任何需要它的控制器方法,但user
仍未保存到websocket会话,因此消息仍然无法发送到特定用户。
如何让Spring“查看”从查询参数中提取的身份验证?
答案 0 :(得分:0)
绕过内置的连接级Spring机制来确定身份验证。相反,通过在客户端的Stomp标头中设置身份验证令牌,将其设置为消息级别。请参阅我在此概述的方法: