我的目标是将具有正确 header 的浏览器客户端与服务器连接。我从 StompClient 传递这些 header 。
我在 header 中传递 token 的 UI 代码是
function connect() {
var socket = new SockJS('/websocket/api/add');
stompClient = Stomp.over(socket);
stompClient.connect({"token" : "12345"}, function(frame) {
setConnected(true);
console.log('Connected: ' + frame);
});
}
在后端,我可以读取 ChannelInterceptorAdapter 的 preSend() 方法中的 header
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
MessageHeaders headers = message.getHeaders();
System.out.println("preSend : HEADERS : {}" + headers);
return super.preSend(message, channel);
}
但在这里我无法关闭 wesocket session 。我们怎样才能做到这一点?
此外,我能够关闭 websocket session ,但无法在 WebSocketHandlerDecorator 的 afterConnectionEstablished() 方法中接收 header
public void configureWebSocketTransport(final WebSocketTransportRegistration registration) {
registration.addDecoratorFactory(new WebSocketHandlerDecoratorFactory() {
@Override
public WebSocketHandler decorate(final WebSocketHandler handler) {
return new WebSocketHandlerDecorator(handler) {
@Override
public void afterConnectionEstablished(final WebSocketSession session) throws Exception {
session.close(CloseStatus.NOT_ACCEPTABLE);
super.afterConnectionEstablished(session);
}
};
}
});
super.configureWebSocketTransport(registration);
}
有人可以指导我如何根据我们从服务器端 UI 传递的 header 关闭 websocketsession 吗?
最佳答案
您可以尝试在连接建立时通过消息将客户端的token发送给服务器,然后让服务器将该 session 保存到一个map中,其key就是相应的token。
因此,当您想通过 token 关闭 session 时,您可以使用 token 从该映射查询 session 。
<小时/>示例代码:
保存 session 及其 token :
@Override
public void handleMessage(WebSocketSession session, WebSocketMessage<?> message) throws Exception {
String messageToString = message.getPayload().toString();
if (messageToString.startsWith("token=")) {
tokenToSessionMapping.put(messageToString.substring("token=".length()));
}
// Other handling message code...
}
通过 token 关闭 session :
WebSocketSession sessionByToken = tokenToSessionMapping.get(token);
if (sessionByToken != null && sessionByToken.isOpen()) {
sessionByToken.close(CloseStatus.NOT_ACCEPTABLE);
}
还有其他需要注意的事情:
由于
tokenToSessionMapping
是静态的并且在 session 之间共享。您应该使用线程安全的实现,例如 ConcurrentHashMap。当 session 关闭时,您最好从映射
tokenToSessionMapping
中删除相应的条目。否则 map 大小只会不断增长。您可以通过重写方法afterConnectionClosed()
来完成此操作。@Override public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception { Log.info("Socket session closed: {}", status.toString()); String foundKey = null; for (Map.Entry<String, String> entry : tokenToSessionMapping.entrySet()) { if (Objects.equals(entry.getValue(), session)) { foundKey = entry.getKey(); } } if (foundKey != null) { tokenToSessionMapping.remove(foundKey); } }
关于java - 根据从 UI 传递的 token 在服务器端断开 Websocket,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42279002/