java 如何在 Spring WebSocketStompClient 中获取会话 ID?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/42243543/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 06:28:45  来源:igfitidea点击:

How to get Session Id in Spring WebSocketStompClient?

javaspringsessionstompspring-websocket

提问by Irina

How to get session id in Java Spring WebSocketStompClient?

如何在 Java Spring WebSocketStompClient 中获取会话 ID?

I have WebSocketStompClient and StompSessionHandlerAdapter, which instances connect fine to websocket on my server. WebSocketStompClient use SockJsClient.
But I don't know how get session id of websocket connection. In the code with stomp session handler on client side

我有 WebSocketStompClient 和 StompSessionHandlerAdapter,它们的实例可以很好地连接到我服务器上的 websocket。WebSocketStompClient 使用 SockJsClient。
但我不知道如何获取 websocket 连接的会话 ID。在客户端带有 stomp 会话处理程序的代码中

   private class ProducerStompSessionHandler extends StompSessionHandlerAdapter {
            ...
            @Override
            public void afterConnected(StompSession session, StompHeaders  connectedHeaders) {
            ...
            }

stomp session contains session id, which is different from session id on the server. So from this ids:

stomp session 包含 session id,它与服务器上的 session id 不同。所以从这个ID:

DEBUG ... Processing SockJS open frame in WebSocketClientSockJsSession[id='d6aaeacf90b84278b358528e7d96454a...

DEBUG ... DefaultStompSession - Connection established in session id=42e95c88-cbc9-642d-2ff9-e5c98fb85754

I need first session id, from WebSocketClientSockJsSession. But I didn't found in WebSocketStompClient or SockJsClient any method to retrieve something like session id...

我需要来自 WebSocketClientSockJsSession 的第一个会话 ID。但是我没有在 WebSocketStompClient 或 SockJsClient 中找到任何方法来检索诸如会话 ID 之类的东西......

回答by Dhiraj Ray

To get session id you need to define your own interceptor as below and set the session id as a custom attribute.

要获取会话 id,您需要定义自己的拦截器,如下所示,并将会话 id 设置为自定义属性。

public class HttpHandshakeInterceptor implements HandshakeInterceptor {

    @Override
    public boolean beforeHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
            Map attributes) throws Exception {
        if (request instanceof ServletServerHttpRequest) {
            ServletServerHttpRequest servletRequest = (ServletServerHttpRequest) request;
            HttpSession session = servletRequest.getServletRequest().getSession();
            attributes.put("sessionId", session.getId());
        }
        return true;
    }

Now you can get the same session id in the controller class.

现在您可以在控制器类中获得相同的会话 ID。

@MessageMapping("/message")
public void processMessageFromClient(@Payload String message, SimpMessageHeaderAccessor  headerAccessor) throws Exception {
        String sessionId = headerAccessor.getSessionAttributes().get("sessionId").toString();

    }

回答by Arseniy

You can use @Headerannotation to access sessionId:

您可以使用@Header注解来访问 sessionId:

@MessageMapping("/login")
public void login(@Header("simpSessionId") String sessionId) {
    System.out.println(sessionId);
}

And it works fine for me without any custom interceptors

它对我来说很好,没有任何自定义拦截器

回答by dimirsen

There is a way to extract sockjs sessionId via Reflection API:

有一种方法可以通过反射 API 提取 sockjs sessionId:

public void afterConnected(StompSession session, StompHeaders connectedHeaders) {
    // we need another sessionId!
    System.out.println("New session established : " + session.getSessionId());
    DefaultStompSession defaultStompSession =
            (DefaultStompSession) session;
    Field fieldConnection = ReflectionUtils.findField(DefaultStompSession.class, "connection");
    fieldConnection.setAccessible(true);

    String sockjsSessionId = "";
    try {
        TcpConnection<byte[]> connection = (TcpConnection<byte[]>) fieldConnection.get(defaultStompSession);
        try {
            Class adapter = Class.forName("org.springframework.web.socket.messaging.WebSocketStompClient$WebSocketTcpConnectionHandlerAdapter");
            Field fieldSession = ReflectionUtils.findField(adapter, "session");
            fieldSession.setAccessible(true);
            WebSocketClientSockJsSession sockjsSession = (WebSocketClientSockJsSession) fieldSession.get(connection);
            sockjsSessionId = sockjsSession.getId(); // gotcha!
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
    } catch (IllegalAccessException e) {
        e.printStackTrace();
    }

    if (StringUtils.isBlank(sockjsSessionId)) {
        throw new IllegalStateException("couldn't extract sock.js session id");
    }

    String subscribeLink = "/topic/auth-user" + sockjsSessionId;
    session.subscribe(subscribeLink, this);
    System.out.println("Subscribed to " + subscribeLink);
    String sendLink = "/app/user";
    session.send(sendLink, getSampleMessage());
    System.out.println("Message sent to websocket server");
}

Can be seen here: tutorial

可以在这里看到:教程