web-dev-qa-db-ja.com

Spring WebSocketStompClientでセッションIDを取得するにはどうすればよいですか?

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セッションには、サーバー上のセッションIDとは異なるセッション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などを取得するメソッドが見つかりませんでした...

6
Irina

セッション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();

    }
10
Dhiraj Ray

@Headerアノテーションを使用してsessionIdにアクセスできます。

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

そして、カスタムインターセプターがなくても問題なく動作します

7
Arseniy

ReflectionAPIを介してsockjssessionIdを抽出する方法があります。

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

1
dimirsen