用户会话管理
为 WebSockets 实施高级用户会话管理,将 HTTP 会话与 WebSocket 会话关联起来。
用户会话管理 是 CoddyKit 上的免费 WebSockets & Real-Time Systems with Spring 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 WebSockets & Real-Time Systems with Spring 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 WebSockets & Real-Time Systems with Spring 课程共包含 4 节课。
本课时的部分内容尚未翻译,以英文显示。
Understanding User Sessions
In web applications, a "session" helps a server remember a user across multiple requests. It's like a temporary memory for each user.
For traditional HTTP, sessions are often managed with cookies. They allow you to store user-specific data, like login status or cart items, between page loads.
WebSockets: Session Challenges
Unlike HTTP, WebSockets establish a persistent, full-duplex connection. This connection doesn't inherently carry the same session context as an HTTP request.
This means if a user logs in via HTTP and then opens a WebSocket, the WebSocket connection won't automatically know who the user is without specific setup.
- HTTP Session: Short-lived, request-response.
- WebSocket Session: Long-lived, persistent connection.
Bridging HTTP & WebSocket Sessions
To build rich real-time applications, you often need the WebSocket connection to know about the user's HTTP session context.
For example, you might need to know if a user is authenticated, their user ID, or other profile details that were established during their initial HTTP login.
Spring provides mechanisms to "bridge" this gap during the WebSocket handshake.
The Handshake Interceptor
Spring's primary tool for linking HTTP and WebSocket sessions is the HttpSessionHandshakeInterceptor.
This interceptor runs during the WebSocket handshake, which is the initial HTTP request that upgrades to a WebSocket connection. It can copy attributes from the current HTTP session to the WebSocket session.
- What it does: Copies HTTP session attributes.
- When it runs: During the WebSocket handshake.
Configuring Session Interceptor
To use the HttpSessionHandshakeInterceptor, you need to register it within your WebSocket configuration. This tells Spring to apply the interceptor when a WebSocket connection is being established.
It's typically added in your WebSocketMessageBrokerConfigurer implementation:
public class WebSocketConfig extends AbstractWebSocketMessageBrokerConfigurer {
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.addInterceptors(new HttpSessionHandshakeInterceptor())
.withSockJS();
}
}Accessing Linked Session Data
Once the HttpSessionHandshakeInterceptor has done its job, you can access the copied HTTP session attributes within your WebSocket message handlers.
Commonly, you'll want to access the Principal (representing the authenticated user) or other custom attributes you've stored in the HTTP session.
@Controller
public class MyWebSocketController {
@MessageMapping("/hello")
public void handleMessage(@Payload String message, Principal principal) {
String username = principal.getName();
System.out.println("Message from " + username + ": " + message);
// ... use username for user-specific logic
}
}WebSocket-Specific Data
Besides copying HTTP session data, you can also store information directly within the WebSocketSession itself. This data is specific to that particular WebSocket connection.
This is useful for managing connection-specific states, like a user's current chat room, notification preferences for this connection, or other transient data.
@EventListener
public void handleSessionConnect(SessionConnectedEvent event) {
StompHeaderAccessor accessor = StompHeaderAccessor.wrap(event.getMessage());
WebSocketSession session = (WebSocketSession) accessor.getSessionAttributes().get("webSocketSession");
if (session != null) {
session.getAttributes().put("customKey", "customValue");
}
System.out.println("User connected: " + accessor.getUser().getName());
}Managing Session Lifecycle
Spring allows you to listen to WebSocket session lifecycle events. This is crucial for cleaning up resources or updating user status when connections are established or closed.
You can use @EventListener with SessionConnectedEvent and SessionDisconnectEvent to react to these changes.
SessionConnectedEvent: Fired when a new STOMP session is established.SessionDisconnectEvent: Fired when a STOMP session is closed.
Runnable: Handshake Interceptor
This Spring Boot example configures a WebSocket endpoint with HttpSessionHandshakeInterceptor. When a client connects, the interceptor helps link the HTTP session (if any) to the WebSocket session.
We demonstrate a simple message handler that could access the authenticated user's Principal. If Spring Security were enabled, principal.getName() would return the logged-in username.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.messaging.handler.annotation.MessageMapping;
import org.springframework.messaging.simp.config.MessageBrokerRegistry;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.config.annotation.EnableWebSocketMessageBroker;
import org.springframework.web.socket.config.annotation.StompEndpointRegistry;
import org.springframework.web.socket.config.annotation.WebSocketMessageBrokerConfigurer;
import org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor;
import java.security.Principal;
@SpringBootApplication
@EnableWebSocketMessageBroker
public class WebSocketSessionApp {
public static void main(String[] args) {
SpringApplication.run(WebSocketSessionApp.class, args);
}
@Configuration
public static class WebSocketConfig implements WebSocketMessageBrokerConfigurer {
@Override
public void configureMessageBroker(MessageBrokerRegistry config) {
config.enableSimpleBroker("/topic");
config.setApplicationDestinationPrefixes("/app");
}
@Override
public void registerStompEndpoints(StompEndpointRegistry registry) {
registry.addEndpoint("/ws")
.addInterceptors(new HttpSessionHandshakeInterceptor())
.withSockJS();
}
}
@Controller
public static class WebSocketGreetingController {
@MessageMapping("/hello")
public void greeting(Principal principal) {
if (principal != null) {
System.out.println("Message from authenticated user: " + principal.getName());
} else {
System.out.println("Message from unauthenticated user (Principal is null).");
}
}
}
}Quick Check: Handshake Interceptor
Test your understanding of the HttpSessionHandshakeInterceptor.
Recap: Session Management
We've explored how to manage user sessions in Spring WebSocket applications, particularly how to link HTTP session context to WebSocket sessions.
- The
HttpSessionHandshakeInterceptoris key for copying HTTP session attributes during the handshake. - You can access authenticated user information (
Principal) in WebSocket handlers. @EventListenerhelps manage connection and disconnection events.
Proper session management ensures your real-time features are personalized and secure for each user.
常见问题解答
「用户会话管理」课时是免费的吗?
是的 — 「用户会话管理」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 WebSockets & Real-Time Systems with Spring 课程的其余内容,请升级到 CoddyKit PRO。 WebSockets & Real-Time Systems with Spring 课程共包含 4 节课。
「用户会话管理」这节课中我会学到什么?
为 WebSockets 实施高级用户会话管理,将 HTTP 会话与 WebSocket 会话关联起来。 你通过在浏览器中直接运行的动手代码来练习 WebSockets & Real-Time Systems with Spring,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 WebSockets & Real-Time Systems with Spring 需要有经验吗?
无需任何先前经验。CoddyKit 上的 WebSockets & Real-Time Systems with Spring 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「用户会话管理」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 WebSockets & Real-Time Systems with Spring 课中编写并运行代码吗?
能。每节 WebSockets & Real-Time Systems with Spring 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。