SpringSession header/cookie/attribute存放 session id
SpringSession header/cookie/attribute存放 SessionID(死磕)
疯狂创客圈 Java 高并发【 亿级流量聊天室实战】实战系列 【博客园总入口 】
架构师成长+面试必备之 高并发基础书籍 【Netty Zookeeper Redis 高并发实战 】
前言
Crazy-SpringCloud 微服务脚手架 &视频介绍:
Crazy-SpringCloud 微服务脚手架,是为 Java 微服务开发 入门者 准备的 学习和开发脚手架。并配有一系列的使用教程和视频,大致如下:
高并发 环境搭建 图文教程和演示视频,陆续上线:
| 中间件 | 链接地址 |
|---|---|
| Linux Redis 安装(带视频) | Linux Redis 安装(带视频) |
| Linux Zookeeper 安装(带视频) | Linux Zookeeper 安装, 带视频 |
| Windows Redis 安装(带视频) | Windows Redis 安装(带视频) |
| RabbitMQ 离线安装(带视频) | RabbitMQ 离线安装(带视频) |
| ElasticSearch 安装, 带视频 | ElasticSearch 安装, 带视频 |
| Nacos 安装(带视频) | Nacos 安装(带视频) |
Crazy-SpringCloud 微服务脚手架 图文教程和演示视频,陆续上线:
| 组件 | 链接地址 |
|---|---|
| Eureka | Eureka 入门,带视频 |
| SpringCloud Config | springcloud Config 入门,带视频 |
| spring security | spring security 原理+实战 |
| Spring Session | SpringSession 独立使用 |
| 分布式 session 基础 | RedisSession (自定义) |
| 重点: springcloud 开发脚手架 | springcloud 开发脚手架 |
| SpingSecurity + SpringSession 死磕 (写作中) | SpingSecurity + SpringSession 死磕 |
小视频以及所需工具的百度网盘链接,请参见 疯狂创客圈 高并发社群 博客
场景和问题
由于 SpingSecurity + SpringSession 整合场景,涉及到SpringSession SessionID 存取的问题。
具体问题:
由 SpringSecurity 将sessionID放在了 request 的 attribute中, SpringSession 需要从 request 的 attribute中取得。
SpringSession 自带的 sessionId 存取器:
SpringSession中对于sessionId的存取相关的策略,是通过HttpSessionIdResolver这个接口来体现的。HttpSessionIdResolver有两个实现类:

1: SpringSession header 存取 SessionID
HeaderHttpSessionIdResolver,通过从请求头header中解析出sessionId。
具体地说,这个实现将允许使用HeaderHttpSessionIdResolver(String)来指定头名称。还可以使用便利的工厂方法来创建使用公共头名称(例如“X-Auth-Token”和“authenticing-info”)的实例。创建会话时,HTTP响应将具有指定名称和sessionId值的响应头。
如果要使用HeaderHttpSessionIdResolver ,方法为:
增加Spring Bean,类型为 HeaderHttpSessionIdResolver
import org.springframework.context.annotation.Bean;
import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession;
import org.springframework.session.web.http.HeaderHttpSessionIdResolver;
//设置session失效时间为30分钟
@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 1800)
public class HttpSessionConfig {
@Bean
public HeaderHttpSessionIdResolver headerHttpSessionIdResolver() {
return new HeaderHttpSessionIdResolver("x-auth-token");
}
}
sessionID放到header中可以实现共享了
更加完整的内容,参见 博文
2: SpringSession cookie 存取 SessionID
这种策略对应的实现类是CookieHttpSessionIdResolver,通过从Cookie中获取session。
下面为 CookieHttpSessionIdResolver 源码, 仅供参考。如果不做定制, SpringSession 默认的 IdResolver 就是这种了。
/*
* Copyright 2014-2017 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.session.web.http;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.session.web.http.CookieSerializer.CookieValue;
public final class CookieHttpSessionIdResolver implements HttpSessionIdResolver {
private static final String WRITTEN_SESSION_ID_ATTR = CookieHttpSessionIdResolver.class
.getName().concat(".WRITTEN_SESSION_ID_ATTR");
private CookieSerializer cookieSerializer = new DefaultCookieSerializer();
//重点:从cookie 取得sessionid
@Override
public List<String> resolveSessionIds(HttpServletRequest request) {
return this.cookieSerializer.readCookieValues(request);
}
//重点:设置 sessionid 到 cookie
@Override
public void setSessionId(HttpServletRequest request, HttpServletResponse response,
String sessionId) {
if (sessionId.equals(request.getAttribute(WRITTEN_SESSION_ID_ATTR))) {
return;
}
request.setAttribute(WRITTEN_SESSION_ID_ATTR, sessionId);
this.cookieSerializer
.writeCookieValue(new CookieValue(request, response, sessionId));
}
@Override
public void expireSession(HttpServletRequest request, HttpServletResponse response) {
this.cookieSerializer.writeCookieValue(new CookieValue(request, response, ""));
}
/**
* Sets the {@link CookieSerializer} to be used.
*
* @param cookieSerializer the cookieSerializer to set. Cannot be null.
*/
public void setCookieSerializer(CookieSerializer cookieSerializer) {
if (cookieSerializer == null) {
throw new IllegalArgumentException("cookieSerializer cannot be null");
}
this.cookieSerializer = cookieSerializer;
}
}
3 SpringSession Attribute 存取 SessionID
如果要从 Attribute 存取 SessionID ,则必须实现一个定制的 HttpSessionIdResolver,代码如下:
package com.crazymaker.springcloud.standard.config;
import com.crazymaker.springcloud.common.constants.SessionConstants;
import lombok.Data;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.session.web.http.HeaderHttpSessionIdResolver;
import org.springframework.session.web.http.HttpSessionIdResolver;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collections;
import java.util.List;
@Data
public class CustomedSessionIdResolver implements HttpSessionIdResolver {
private RedisTemplate<Object, Object> redisTemplet = null;
private static final String HEADER_AUTHENTICATION_INFO = "Authentication-Info";
private final String headerName;
/**
* Convenience factory to create {@link HeaderHttpSessionIdResolver} that uses
* "X-Auth-Token" header.
*
* @return the instance configured to use "X-Auth-Token" header
*/
public static HeaderHttpSessionIdResolver xAuthToken() {
return new HeaderHttpSessionIdResolver(SessionConstants.SESSION_SEED);
}
/**
* Convenience factory to create {@link HeaderHttpSessionIdResolver} that uses
* "Authentication-Info" header.
*
* @return the instance configured to use "Authentication-Info" header
*/
public static HeaderHttpSessionIdResolver authenticationInfo() {
return new HeaderHttpSessionIdResolver(HEADER_AUTHENTICATION_INFO);
}
/**
* The name of the header to obtain the session id from.
*
* @param headerName the name of the header to obtain the session id from.
*/
public CustomedSessionIdResolver(String headerName) {
if (headerName == null) {
throw new IllegalArgumentException("headerName cannot be null");
}
this.headerName = headerName;
}
//重点,springsession 用来获得sessionID
@Override
public List<String> resolveSessionIds(HttpServletRequest request) {
String headerValue = request.getHeader(this.headerName);
if (StringUtils.isEmpty(headerValue)) {
headerValue = (String) request.getAttribute(SessionConstants.SESSION_SEED);
if (!StringUtils.isEmpty(headerValue)) {
headerValue = SessionConstants.getRedisSessionID(headerValue);
}
}
if (StringUtils.isEmpty(headerValue)) {
headerValue = (String) request.getAttribute(SessionConstants.SESSION_ID);
}
return (headerValue != null) ?
Collections.singletonList(headerValue) : Collections.emptyList();
}
//重点,springsession 用来存放sessionid
@Override
public void setSessionId(HttpServletRequest request, HttpServletResponse response,
String sessionId) {
response.setHeader(this.headerName, sessionId);
}
@Override
public void expireSession(HttpServletRequest request, HttpServletResponse response) {
response.setHeader(this.headerName, "");
}
/**
* hash的赋值去设置
*
* @param key key
* @param hkey hkey
* @param value value
*/
public void hset(String key, String hkey, String value) {
redisTemplet.opsForHash().put(key, hkey, value);
}
/**
* hash的赋值去取值
*
* @param key key
* @param hkey hkey
*/
public String hget(String key, String hkey) {
return (String) redisTemplet.opsForHash().get(key, hkey);
}
public Object getSessionId(String loginName) {
return hget(SessionConstants.SESSION_ID + ":KEYS", loginName);
}
public void setSessionId(String loginName, String sid) {
hset(SessionConstants.SESSION_ID + ":KEYS", loginName, sid);
}
}
SpringSession SessionID 存取 原理
牛逼的 SessionRepositoryFilter 过滤器: 位于 spring-session-core 包中,间接涉及到 SpringSession 的ID的获取和保存。
SessionRepositoryFilter 作为 SpringSession 的重要的一环,涉及两个非常重要的工作:
(1)请求处理前,SessionRepositoryFilter 通过多层函数调用, 从 HttpSessionIdResolver 中取得 SessionID。
(2)请求 处理完成后,SessionRepositoryFilter 负责session的提交(如:保存到redis),并且通过 HttpSessionIdResolver 输出sessionID。

近景图

具体,请关注 Java 高并发研习社群 【博客园 总入口 】
最后,介绍一下疯狂创客圈:疯狂创客圈,一个Java 高并发研习社群 【博客园 总入口 】
疯狂创客圈,倾力推出:面试必备 + 面试必备 + 面试必备 的基础原理+实战 书籍 《Netty Zookeeper Redis 高并发实战》
疯狂创客圈 Java 死磕系列
- Java (Netty) 聊天程序【 亿级流量】实战 开源项目实战
- Netty 源码、原理、JAVA NIO 原理
- Java 面试题 一网打尽
- 疯狂创客圈 【 博客园 总入口 】
SpringSession header/cookie/attribute存放 session id的更多相关文章
- 【转】Session ID/session token 及和cookie区别
Session + Cookie 知识收集! cookie机制采用的是在客户端保持状态的方案.它是在用户端的会话状态的存贮机制,他需要用户打开客户端的cookie支持.cookie的作用就是为了解决 ...
- HTTP基础--cookie机制和session机制
1.介绍cookie和session的区别,怎么获取与使用?(这个问题比较开放,可深可浅,现在将这里涉及的主要问题总计如下答案) 答: 一.cookie机制和session机制的区别 cookie机制 ...
- cookie机制和session机制的原理和区别[转]
一.cookie机制和session机制的区别 具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案. 同时我们也看到,由于在服务器端保持状态的 ...
- cookie机制和session机制的区别(面试题)
一.cookie机制和session机制的区别 具体来说cookie机制采用的是在客户端保持状态的方案,而session机制采用的是在服务器端保持状态的方案. 同时我们也看到,由于才服务器端保持状态的 ...
- PHP cookie禁用时session 方案
在PHP中使用过SESSION的朋友可能会碰到这么一个问题,SESSION变量不能跨页传递.这令我苦恼了好些日子,最终通过查资料思考并解决了这个问题.我认为,出现这个问题的原因有以下几点: 1.客户端 ...
- Cookie禁用 获取session
转自:http://blog.csdn.net/u010433704/article/details/40950599 Cookie与 Session,一般认为是两个独立的东西,Session采用的是 ...
- 关于PHP中浏览器禁止Cookie后,Session能使用吗?
sessionid是存储在cookie中的,解决方案如下: Session URL重写,保证在客户端禁用或不支持COOKIE时,仍然可以使用Session session机制.session机制是一种 ...
- php中如何传递Session ID
一般通过在各个页面之间传递的唯一的 Session ID,并通过 Session ID 提取这个用户在服务器中保存的 Session 变量,来跟踪一个用户.常见的 Session ID 传送方法主要有 ...
- Session id实现通过Cookie来传输方法及代码参考
1. Web中的Session指的就是用户在浏览某个网站时,从进入网站到浏览器关闭所经过的这段时间,也就是用户浏览这个网站所花费的时间.因此从上述的定义中我们可以看到,Session实际上是一个特定的 ...
随机推荐
- ELK-logstash基本用法
一:logstash介绍 Logstash在elk系统中为数据存储,报表查询和日志解析创建了一个功能强大的管道链.Logstash提供了多种多样的 input,filters,codecs和outpu ...
- python爬虫--selenium模块.上来自己动!
selenium 基本操作 from selenium import webdriver from time import sleep #实例化一个浏览器对象 bro = webdriver.Chro ...
- 关于toString的自动调用
class a{ } class b extends a{ String rr = "zzz"; public String toString(){ return "aa ...
- 《Java基础知识》序列化与反序列化详解
序列化的作用:为了不同jvm之间共享实例对象的一种解决方案.由java提供此机制. 序列化应用场景: 1. 分布式传递对象. 2. 网络传递对象. 3. tomcat关闭以后会把session对象序列 ...
- Redis Cluster 的数据分片机制
上一篇<分布式数据缓存中的一致性哈希算法> 文章中讲述了一致性哈希算法的基本原理和实现,今天就以 Redis Cluster 为例,详细讲解一下分布式数据缓存中的数据分片,上线下线时数据迁 ...
- 【BZOJ 3771】Triple
Problem Description 给出 \(n\) 个物品,第 \(i\) 个物品体积为 \(a_i\) . 对于每个体积 \(V\) ,求选出 \(3\) 个物品,体积之和为 \(V\) 的方 ...
- Maven 项目在 Eclipse 的创建配置
第1步 New 菜单 Other.. -> Maven -> Maven Project ,然后单击 Next .如下图所示 第2步 在New Maven Project向导中,选择Cre ...
- javaWeb实现验证码--代码超简单
1.前端显示 HTML: <h3>验证码:</h3> <input type="text" name="validationCode&quo ...
- 2019有赞中高级Java工程师面试题与解答
说说JVM的内存分区 线程私有的区域 程序计数器:JVM中程序计数器相当于汇编语言中的CPU中的寄存器,保存程序当前执行的指令的地址. 虚拟机栈:Java方法执行的栈由许多个栈帧构成,每个栈帧对应一个 ...
- js实现常见排序算法
电脑配置 CPU:AMD X4 640 内存: 宏想 DDR3 1600MHz 8g 主板:华擎 980DE3/U3S3 R2.0 浏览器:chrome 79.0.3945.88(正式版本) (64 ...