简体   繁体   English

在 Spring/Stomp/Websocket/Messaging 中更改会话 ID

[英]Change session id in Spring/Stomp/Websocket/Messaging

I am writing an application with spring messaging and stomp and rabbitmq.我正在编写一个带有 spring 消息传递、stomp 和 rabbitmq 的应用程序。 My application already sends messages from the browser to rabbitmq and back.我的应用程序已经将消息从浏览器发送到 rabbitmq 并返回。 But i dont want the predefined rabbitmq queue names based on the session id.但我不想要基于会话 id 的预定义 rabbitmq 队列名称。 I want to change the session id on connect.我想在连接时更改会话 ID。 This is what i tried:这是我试过的:

@Component
public class MyListener {

    private Logger logger = LoggerFactory.getLogger(getClass().getSimpleName());

    @EventListener
    public void x(SessionConnectEvent event) {
        Map<String, Object> headers = event.getMessage().getHeaders();
        String id = headers.get("simpSessionId").toString();
        logger.info("My current session id is " + id);
        headers.put("sessionId", "fred");
    }
}

Error is: the map is immutable错误是:地图是不可变的

You need to update the sessionId before the handshake is done between client <-> server, that is when the headers attributes are defined.您需要在客户端 <-> 服务器之间完成握手之前更新sessionId ,即定义 headers 属性时。

On the other hand, the listener SessionConnectEvent is executed only after the handshake is done.另一方面,侦听器SessionConnectEvent仅在握手完成后才执行。

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", "mySessiond");
    }
    return true;
}

public void afterHandshake(ServerHttpRequest request, ServerHttpResponse response, WebSocketHandler wsHandler,
        Exception ex) {
}
}

Also don't forget to register the interceptor on the specific endpoint也不要忘记在特定端点上注册拦截器

 @Override
 public void registerStompEndpoints(StompEndpointRegistry registry) {
  registry.addEndpoint("/greeting").addInterceptors(new HttpHandshakeInterceptor());
 }

Changing the session ID was not the correct way.更改会话 ID 不是正确的方法。 I used ServletFilter for Cookie and Security Checks and @SendTo for the correct use of rabbitmq queues.我使用 ServletFilter 进行 Cookie 和安全检查,并使用 @SendTo 正确使用 rabbitmq 队列。

You can change the session id by creating a Principal for each handshake and then you can target each connected session with the provided username :您可以通过为每次握手创建一个 Principal 来更改会话 ID,然后您可以使用提供的用户名定位每个连接的会话:

class CustomHandshake extends DefaultHandshakeHandler {
    @Override
    public Principal determineUser(ServerHttpRequest request, WebSocketHandler wsHandler, Map<String, Object> attributes) {
        Principal principal = request.getPrincipal();
        if (principal == null) {
            principal = new AnonymousPrincipal();

            String uniqueName = UUID.randomUUID().toString();

            ((AnonymousPrincipal) principal).setName(uniqueName);
        }

        return principal;
    }

}

Do not forget to register the handler as below :不要忘记注册处理程序如下:

.setHandshakeHandler(new CustomHandshake())

hope this is helpful希望这是有帮助的

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM