前言
刚开始想进行认证感觉还是蛮简单的,也只需要让websocket 的Headers
上也带authorization
在加上token 的值不就完事了吗。
但websocket 不支持自定义Headers
头所以不行,但ws 允许在Sec-WebSocket-Protocol
的请求头加入自定义的参数,也就是说只需要在spring security 中在加入一个对于Sec-WebSocket-Protocol
的检测就行了。
添加对 Sec-WebSocket-Protocol 的判断
这里的WSHeader
其实就是Sec-WebSocket-Protocol
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
|
private String getToken(HttpServletRequest request) { String token = request.getHeader(header); if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { token = token.replace(Constants.TOKEN_PREFIX, ""); } else { token = request.getHeader(WSHeader); if (StringUtils.isNotEmpty(token)) { HttpServletResponse response = ServletUtils.getResponse(); response.setHeader(WSHeader, token); } } return token; }
|
经过这样的配置我们的Websocket
的连接端点是肯定可以通过认证了,但还要拿到SpringSecuiry
中的已经登录的用户,判断它是谁?
添加获取用户信息
首先配置好Websocket
的配置
1 2 3 4 5 6 7 8 9 10
| @Configuration public class WebSocketConfig {
@Bean public ServerEndpointExporter serverEndpointExporter() { return new ServerEndpointExporter(); } }
|
这里在配置一个websocket
的连接接口
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @ServerEndpoint("/ws") @Component public class WebSocketController { private Session session; @OnOpen public void OnOpen(Session session) throws IOException { this.session = session; }
@OnMessage public void OnMessage(String msg) throws IOException { }
@OnClose public void OnClose(Session session) throws IOException { } }
|
可以看到每一个用户连入/ws
的这个都会有他们自己唯一一个session
其实如果要是直接 session.
或有一个叫做 ``getUserPrincipal() 的方法继续点下去有一个getName的方法。如果继续追下去打开
debug就会惊奇的发现,
getUserPrincipal()的类型尽然是SpringSecurity的
UsernamePasswordAuthenticationToken`的类,那么这就好办了。我写了一方法。

这里的LoginUser
和SysUser
是我已经重写好SpringSecuriy
中的登录用户的类,请改成你自己的即可。
1 2 3 4 5 6 7 8 9
|
public SysUser getSysUser() { UsernamePasswordAuthenticationToken userPrincipal = (UsernamePasswordAuthenticationToken) this.session.getUserPrincipal(); LoginUser principal = (LoginUser) userPrincipal.getPrincipal(); return principal.getUser(); }
|