java - 根据从 UI 传递的 token 在服务器端断开 Websocket

标签 java spring-mvc websocket stomp

我的目标是将具有正确 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);                
    });
}

在后端,我可以读取 ChannelInterceptorAdapterpreSend() 方法中的 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 ,但无法在 WebSocketHandlerDecoratorafterConnectionEstablished() 方法中接收 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);
}

还有其他需要注意的事情:

  1. 由于 tokenToSessionMapping 是静态的并且在 session 之间共享。您应该使用线程安全的实现,例如 ConcurrentHashMap。

  2. 当 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/

相关文章:

java - entityManagerFactory 未命名时 "entityManagerFactory"

java - 使用https错误上传文件?

java - 什么是shell脚本、makefile和ant文件

java - Spring MVC 应用程序可以是多线程的,即使它的 servlet 不是吗?

java - spring mvc jquery ajax响应作为json编码问题

Spring MVC : Redirecting from a base controller - How to get the path to redirect to?

node.js - 无法安装nodejs模块

java - 如何测试@Cacheable?

android - 如何在 android 上使用高速公路库在 websocket 中添加 header ?

C# WebSocket 版本 8+ 服务器通信