在spring中获取websocket会话的关联HTTPSession
Posted
技术标签:
【中文标题】在spring中获取websocket会话的关联HTTPSession【英文标题】:Get associated HTTPSession of websocket session in spring 【发布时间】:2014-11-25 05:37:46 【问题描述】:我有一个使用 stomp 的简单 Web 套接字应用程序。当用户访问页面时,它会自动与服务器建立连接。用户通过 spring security 进行身份验证。当用户关闭浏览器时,我希望用户自动注销。为此,我创建了一个侦听器来侦听 SessionDisconnectEvent。问题是我没有与 websocket 会话关联的 httpSession 的句柄?是否想从 websocket 会话中获取 httpsession?
这是我的代码:
<websocket:message-broker application-destination-prefix="/test">
<websocket:stomp-endpoint path="/sbapp">
<websocket:handshake-interceptors>
<bean class="com.sample.HttpSessionIdHandshakeInterceptor"></bean>
</websocket:handshake-interceptors>
<websocket:sockjs />
</websocket:stomp-endpoint>
<websocket:stomp-broker-relay prefix="/topic,/queue,/user" relay-host="localhost" relay-port="61613"/>
</websocket:message-broker>
这是我的 websocket 会话监听器:
@Component
public class StompDisconnectListener implements ApplicationListener<SessionDisconnectEvent>
@Override
public void onApplicationEvent(SessionDisconnectEvent event)
System.out.println("Stomp disconnect: " + event.getSessionId());
我需要一种方法,当我收到断开连接事件时,我会收到相应的 HttpSession,然后手动注销 HttpSession。这可能吗?
【问题讨论】:
您找到解决这个问题的好方法了吗?在这里遇到相同的用例。 我也对这个问题的解决方案感兴趣。你最后是怎么解决的? 【参考方案1】:现在 Spring Session 支持 WebSockets。按照this guide 将其添加到您的项目中。然后,在您的 SessionDisconnectEvent 侦听器中,您可以通过这种方式获取 HttpSessionID:
import org.springframework.context.ApplicationListener;
import org.springframework.messaging.simp.SimpMessageHeaderAccessor;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;
public class WebSocketDisconnectHandler<S>
implements ApplicationListener<SessionDisconnectEvent>
public void onApplicationEvent(SessionDisconnectEvent event)
String session = SimpMessageHeaderAccessor.getSessionAttributes(event.getMessage().getHeaders()).get("HTTP.SESSION.ID").toString();
(您可以访问的其他标题值:)
headers simpMessageType=CONNECT, stompCommand=CONNECT, nativeHeaders=X-XSRF-TOKEN=[cb73273e-bff3-4eb7-965d-4c696e22c25a], accept-version=[1.1,1.0], heart-beat=[10000,10000], simpSessionAttributes=HTTP.SESSION.ID=6dd63204-d5ec-4362-8f37-29af5605298d, org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository.CSRF_TOKEN=org.springframework.security.web.csrf.DefaultCsrfToken@10b64145, org.springframework.security.web.csrf.CsrfToken=org.springframework.security.web.csrf.DefaultCsrfToken@10b64145, simpHeartbeat=[J@3955ead4, simpSessionId=3x25c1e5
确保在扩展 ExpiringSession 的 WebSocket 配置文件中将其注册为 bean:
import your.package.WebSocketDisconnectHandler;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.session.ExpiringSession;
@Configuration
public class WebSocketHandlersConfig<S extends ExpiringSession>
@Bean
public WebSocketDisconnectHandler<S> webSocketDisconnectHandler()
return new WebSocketDisconnectHandler<S>();
【讨论】:
【参考方案2】:我认为你需要一个拦截器,没有它你会得到空的sessionAttributes
。
您需要在dispatcher-servlet.xml
中添加HttpSessionHandshakeInterceptor
:
<websocket:message-broker
application-destination-prefix="/test">
<websocket:stomp-endpoint path="/sbapp">
<websocket:handshake-interceptors>
<bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor"/>
</websocket:handshake-interceptors>
<websocket:sockjs session-cookie-needed="true" />
</websocket:stomp-endpoint>
<websocket:simple-broker prefix="/topic, /message" />
</websocket:message-broker>
然后你就可以在控制器中获取会话了:
@MessageMapping("/authorization.action")
public Message authorizationAction(
SimpMessageHeaderAccessor headerAccessor, Message message)
String sessionId = headerAccessor.getSessionId();
Map<String, Object> sessionAttributes = headerAccessor.getSessionAttributes();
System.out.println(sessionId);
System.out.println(sessionAttributes);
// Do something with session
return new Message(...);
这对我有用。
【讨论】:
【参考方案3】:看看下面的帖子。 https://spring.io/blog/2014/09/16/preview-spring-security-websocket-support-sessions
【讨论】:
以上是关于在spring中获取websocket会话的关联HTTPSession的主要内容,如果未能解决你的问题,请参考以下文章
Spring消息传递+安全如何通过websockets登录?
弹簧+WebSocket+STOMP。给特定会话的消息(非用户)
在 Spring Websocket 消息传递的预定方法中获取主体
java - 如何使用simplebroker或rabbitMQ和java spring在websocket中获取所有连接的用户