Websocket获取SpringSecurity用户信息失败问题

问题描述

项目中将用户的信息保存在SpringSecurity的安全上下文中,通过安全上下文获取用户id,但是在Websockt中 UserDetailsImpl userDetails = (UserDetailsImpl) SecurityContextHolder.getContext().getAuthentication().getPrincipal();发生空指针报错

img

问题分析

WebSocket 协议与 HTTP 协议是不同的,它们是两种独立的协议,SpringSecurity是基于http协议的安全框架,所以websocket无法获取SpringSecurity中的安全上下文

解决方法

ws是通过http协议升级而成的,所以可以在握手期间将安全上下文设置在会话的attribute中,然后ws通过attribute获取信息

1
2
3
4
5
6
7
8
9
10
11
12
13
public class WebsocketInterceptor implements HandshakeInterceptor {
@Override
public boolean beforeHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Map<String, Object> map) throws Exception {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
map.put("authentication", authentication);
return true;
}

@Override
public void afterHandshake(ServerHttpRequest serverHttpRequest, ServerHttpResponse serverHttpResponse, WebSocketHandler webSocketHandler, Exception e) {

}
}

获取安全上下文信息

1
Authentication authentication = (Authentication) webSocketSession.getAttributes().get("authentication");