原理:将会话数据直接存储在客户端 Cookie 中
实现:
// Spring Boot 示例
@Bean
public CookieSerializer cookieSerializer() {
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setCookieName("SESSION");
serializer.setUseBase64Encoding(true); // Base64编码
serializer.setUseHttpOnlyCookie(true); // 防XSS
serializer.setCookiePath("/");
serializer.setCookieMaxAge(1800); // 30分钟过期
return serializer;
}
优点:
缺点:
适用场景:会话数据量小(<1KB)的安全非敏感场景
原理:集群节点间同步 Session 数据
实现:
<Cluster className="org.apache.catalina.ha.tcp.SimpleTcpCluster">
<Channel className="org.apache.catalina.tribes.group.GroupChannel">
<Receiver className="org.apache.catalina.tribes.transport.nio.NioReceiver"/>
<Sender className="org.apache.catalina.tribes.transport.ReplicationTransmitter">
<Transport className="org.apache.catalina.tribes.transport.nio.PooledParallelSender"/>
Sender>
Channel>
Cluster>
同步方式:
优点:
缺点:
适用场景:小型集群(≤5节点)且对性能要求不高
原理:会话数据集中存储在外部存储中
// Spring Session JDBC 配置
@EnableJdbcHttpSession
public class SessionConfig {
@Bean
public JdbcIndexedSessionRepository sessionRepository(DataSource dataSource) {
return new JdbcIndexedSessionRepository(dataSource);
}
}
表结构:
CREATE TABLE SPRING_SESSION (
PRIMARY_ID CHAR(36) PRIMARY KEY,
SESSION_ID CHAR(36) NOT NULL,
CREATION_TIME BIGINT NOT NULL,
LAST_ACCESS_TIME BIGINT NOT NULL,
MAX_INACTIVE_INTERVAL INT NOT NULL,
EXPIRY_TIME BIGINT NOT NULL
);
// Spring Session Redis
@EnableRedisHttpSession
public class SessionConfig {
@Bean
public LettuceConnectionFactory connectionFactory() {
return new LettuceConnectionFactory("redis-cluster", 6379);
}
}
Redis数据结构:
Key: spring:session:sessions:
Type: Hash
Fields:
creationTime: 1625000000000
maxInactiveInterval: 1800
lastAccessedTime: 1625001000000
sessionAttr::user: {"id":1001,"name":"John"}
优点:
缺点:
优化技巧:
// 本地二级缓存(Caffeine)
@Bean
public SessionRepositoryCustomizer<RedisIndexedSessionRepository> customize() {
return repo -> repo.setDefaultMaxInactiveInterval(1800);
}
原理:负载均衡器将同一用户的请求固定路由到同一节点
Nginx配置:
upstream backend {
ip_hash; # 基于IP的粘性会话
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}
优点:
缺点:
适用场景:对会话一致性要求不高的传统应用
原理:无状态会话,信息包含在Token中
实现:
// JWT 生成
String jwt = Jwts.builder()
.setSubject("user123")
.claim("roles", "admin,user")
.setExpiration(new Date(System.currentTimeMillis() + 3600000))
.signWith(SignatureAlgorithm.HS256, "secretKey")
.compact();
Token结构:
Header: {"alg":"HS256","typ":"JWT"}
Payload: {"sub":"user123","roles":["admin","user"],"exp":1625005000}
Signature: HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload), secret)
优点:
缺点:
解决方案:
方案 | 扩展性 | 性能 | 可靠性 | 安全性 | 实现复杂度 |
---|---|---|---|---|---|
客户端存储 | ★★★★★ | ★★★★☆ | ★★☆☆☆ | ★☆☆☆☆ | ★★☆☆☆ |
Session复制 | ★★☆☆☆ | ★★☆☆☆ | ★★★★☆ | ★★★★☆ | ★★★☆☆ |
Redis集中存储 | ★★★★★ | ★★★★☆ | ★★★★☆ | ★★★★☆ | ★★★☆☆ |
数据库存储 | ★★★★☆ | ★★☆☆☆ | ★★★★★ | ★★★★☆ | ★★★☆☆ |
粘性会话 | ★★☆☆☆ | ★★★★☆ | ★★☆☆☆ | ★★★☆☆ | ★☆☆☆☆ |
JWT | ★★★★★ | ★★★★★ | ★★★☆☆ | ★★★☆☆ | ★★★★☆ |
首选方案
graph LR
A[会话数据量] -->|<1KB| B(JWT)
A -->|1-10KB| C(Redis集群)
A -->|>10KB| D(数据库+本地缓存)
安全加固
HttpOnly
和Secure
的Cookie// Cookie安全设置
DefaultCookieSerializer serializer = new DefaultCookieSerializer();
serializer.setUseSecureCookie(true); // 仅HTTPS传输
serializer.setSameSite("Strict"); // 防CSRF
高可用设计
// 多级缓存配置
@Bean
public SessionRepository<?> sessionRepository() {
MapSessionRepository memoryRepo = new MapSessionRepository();
RedisIndexedSessionRepository redisRepo = ...;
return new DelegatingSessionRepository(memoryRepo, redisRepo);
}
性能优化
spring.session.redis.flush-mode=immediate
spring:
session:
redis:
flush-mode: immediate # 立即写入
namespace: "app:sessions"
迁移方案
跨域会话
SameSite=None
+ Secure
大Session处理
// 分片存储
public class LargeSessionStrategy {
public void saveFragment(String sessionId, String fragmentKey, byte[] data) {
redisTemplate.opsForHash().put(sessionId, fragmentKey, data);
}
}
实时踢人下线
// 发布会话失效事件
@Autowired
private ApplicationEventPublisher eventPublisher;
public void forceLogout(String sessionId) {
eventPublisher.publishEvent(new SessionDestroyedEvent(sessionId));
redisTemplate.delete("spring:session:sessions:" + sessionId);
}