【问题标题】:How to get Session Id in Spring WebSocketStompClient?如何在 Spring WebSocketStompClient 中获取会话 ID?
【发布时间】:2017-07-03 18:27:57
【问题描述】:

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

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

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

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

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

【问题讨论】:

    标签: java spring session stomp spring-websocket


    【解决方案1】:

    要获取会话 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;
        }
    

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

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

    【讨论】:

    • 谢谢!由于服务器也与javascript客户端一起使用,我通过它的请求将会话ID发送给java客户端。
    • 您可以使用内置的HttpSessionHandshakeInterceptor,而不是编写自己的拦截器。
    • 它还从 websocket 的初始“GET /info”请求中获取了我的 id,与上面的自定义 HandshakeInterceptor 实现看起来大不相同。
    【解决方案2】:

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

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

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

    【讨论】:

    • 成功了,但是客户端的jsessionid和收到的sessionid不匹配。
    • @AdityaGupta - 你找到了获取 sessionid 的解决方案吗,自从 lonkg 以来我也面临同样的问题。
    • @RishiAgrawal 是的,可以使用 Dhiraj 的解决方案接收 sessionid。此外,jsessionid 和 sessionid 是不同的属性。所以他们应该是不匹配的。
    【解决方案3】:

    有一种方法可以通过反射 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");
    }
    

    可以在这里看到:tutorial

    【讨论】:

    • 这太过分了
    猜你喜欢
    • 2012-09-04
    • 2013-05-24
    • 1970-01-01
    • 2011-10-27
    • 1970-01-01
    • 2019-02-20
    • 2019-09-12
    • 2011-03-29
    • 2019-01-22
    相关资源
    最近更新 更多