根据从 UI 传递的令牌断开服务器端的 Websocket
Posted
技术标签:
【中文标题】根据从 UI 传递的令牌断开服务器端的 Websocket【英文标题】:Disconnect Websocket on server side based on a token passed from UI 【发布时间】:2017-02-16 16:06:42 【问题描述】:我的目标是将具有正确标头的浏览器客户端与服务器连接。我从 StompClient 传递这些标头。
我在标题中传递 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() 方法中的标头@Override
public Message<?> preSend(Message<?> message, MessageChannel channel)
MessageHeaders headers = message.getHeaders();
System.out.println("preSend : HEADERS : " + headers);
return super.preSend(message, channel);
但是在这里我无法关闭 wesocket 会话。我们该怎么做?
我也能够关闭 websocket 会话,但我无法在 WebSocketHandlerDecorator
的 afterConnectionEstablished() 方法中接收标头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 传递的标头关闭 websocketsession 吗?
【问题讨论】:
【参考方案1】:您可以尝试在连接建立时通过消息将客户端的令牌发送给服务器,然后让服务器将该会话保存到映射中,其键为对应的令牌。
因此,当您想通过其令牌关闭会话时,您可以使用令牌从该映射中查询会话。
示例代码:
使用令牌保存会话:
@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...
通过令牌关闭会话:
WebSocketSession sessionByToken = tokenToSessionMapping.get(token);
if (sessionByToken != null && sessionByToken.isOpen())
sessionByToken.close(CloseStatus.NOT_ACCEPTABLE);
还有其他需要注意的事项:
因为tokenToSessionMapping
是静态的并且在会话之间共享。您应该使用线程安全的实现,例如 ConcurrentHashMap。
当会话关闭时,您最好从映射tokenToSessionMapping
中删除相应的条目。否则地图大小将继续增长。你可以通过覆盖方法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);
【讨论】:
非常感谢您为我指明了正确的方向 :)以上是关于根据从 UI 传递的令牌断开服务器端的 Websocket的主要内容,如果未能解决你的问题,请参考以下文章
Swagger UI 将身份验证令牌传递给标头中的 API 调用
Springboot:将从swagger UI捕获的JWT令牌自动传递给下游(服务到服务)API调用