我正在开发基于 Spring 4 WebSocket 的多人游戏。我的服务器是无状态的,所以为了识别我使用令牌的玩家。
在为如何通过 WebSockets 识别玩家而苦苦挣扎了一段时间之后,我想出了这个解决方案:在客户端玩家注册是这样的:
var sockjs = new SockJS("http://mygame/games/", null, {server : token});
这会将令牌添加到 url,我已经使用 spring security 设置了一个过滤器:
String requestURI = request.getRequestURI();
String[] parts = StringUtils.split(requestURI, "/");
if (parts.length == 4) {
String token = parts[1];
List<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(new SimpleGrantedAuthority(Role.ROLE_MULTIPLAYER)));
SecurityContextHolder.getContext().setAuthentication(new PreAuthenticatedAuthenticationToken(token, "MULTIPLAYER", authorities));
}
它有效!在所有 WebSockets 请求中,我都有一个 Principal 集。
然而,一些浏览器似乎不支持这一点,例如在Safari中没有设置 Principal,在调试请求时我看到 URL 是正确的并且过滤器工作但没有设置 Principal。同样适用于 IE、Chrome 和 FF 作品。我使用 STOMP ( https://github.com/jmesnil/stomp-websocket ) 作为消息协议。
为什么浏览器之间有不同的行为?是 Spring 还是客户端问题?