Spring session + Redis 实现 Session共享入门
Spring session + Redis 实现 Session 共享入门
最近学习接触到了 nginx 下 多个服务 session 共享问题,spring session 提供了简便的解决方案。
1、session 介绍
由于 HTTP 协议是无状态的协议,所以服务端需要记录用户的状态时,就需要用某种机制来识具体的用户。Session 是另一种记录客户状态的机制,不同的是 Cookie 保存在客户端浏览器中,而 Session 保存在服务器上。客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。这就是 Session。客户端浏览器再次访问时只需要从该 Session 中查找该客户的状态就可以了。
2、session 共享
用户的请求首先会到达前置网关,前置网关根据路由策略将请求分发到后端的服务器,这就会出现第一次的请求会交给服务器 1 处理,下次的请求可能会是服务B处理,如果不做 Session 共享的话,就有可能出现用户在服务 2登录了,下次请求的时候到达服务 2 又要求用户重新登录。
3、Session 登录原理
鉴于 HTTP 是无状态协议,之前已认证成功的用户状态是无法通过协议层面保存下来的,既,无法实现状态管理,因此即使当该用户下一次继续访问,也无法区分他和其他的用户。于是我们会使用 Cookie 来管理 Session,以弥补 HTTP 协议中不存在的状态管理功能。
- 步骤 1:客户端把用户 ID 和密码等登录信息放入报文的实体部分,通常是以 POST 方法把请求发送给服务器。
- 步骤 2:服务器会发放用以识别用户的 Session ID。通过验证从客户端发送过来的登录信息进行身份验证,然后把用户的认证状态与 Session ID 绑定后记录在服务器端。向客户端返回响应时,会在首部字段 Cookie 内写入 Session ID。
- 步骤 3:客户端接收到从服务器端发来的 Session ID 后,会将其作为 Cookie 保存在本地。下次向服务器发送请求时,浏览器会自动发送 Cookie,所以 Session ID 也随之发送到服务器。服务器端可通过验证接收到的 Session ID 识别用户和其认证状态。
4、Spring session + redis 配置
Spring Session 提供了一套创建和管理 Servlet HttpSession 的方案。Spring Session 提供了集群 Session(Clustered Sessions)功能,默认采用外置的 Redis 来存储 Session 数据(不用手动存储到redis中),以此来解决 Session 共享的问题。
4.1、引入依赖
<!-- redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--支持session共享 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
4.2 、redis 配置
#redis
spring.redis.port=6379
spring.redis.host=127.0.0.1
spring.redis.password=123456
spring.redis.database=15
#最大连接数
spring.redis.jedis.pool.max-active=100
#最大等待数
spring.redis.jedis.pool.max-idle=8
#等待时间
spring.redis.jedis.pool.max-wait=60000
#spring-session
spring.session.store-type=redis
4.3、测试
现在模拟用户登录接口,打开浏览器,分别调用 localhost:8080/lin/user/login 和 localhost:8081/lin/user/login两个接口,两次调用端口不同。
@GetMapping(value = "/login")
@ResponseBody
public Result login(HttpSession session) {
if (session.getAttribute("userId") == null) {
//将在redis操作session
session.setAttribute("userId","123456");
logger.info("====session为空=======");
} else {
logger.info("=========session========" + session.getAttribute("userId"));
}
return ResultUtil.success();
}
查看 redis 或 日志,发现只在第一次调用生成 session,因此实现了session的共享。
4.4、注意点
对于不同根域名的场景,要实现一处登录,处处登录,Spring Session不支持
比如:
- www.web.com
- www.myweb.com
- www.webtest.com
ip 和域名会产生不同的 Session ID。
5、Cookie与Session的区别
关于Cookie与Session的区别,就是在面试中经常回答的问题了。
- 作用范围不同,Cookie 保存在客户端(浏览器),Session 保存在服务器端。
- 存取方式的不同,Cookie只能保存 ASCII,Session可以存任意数据类型,比如UserId等。
- 有效期不同,Cookie可设置为长时间保持,比如默认登录功能功能,Session一般有效时间较短,客户端关闭或者Session超时都会失效。
- 隐私策略不同,Cookie存储在客户端,信息容易被窃取;Session存储在服务端,相对安全一些。
- 存储大小不同, 单个Cookie 保存的数据不能超过 4K,Session可存储数据远高于Cookie。
参考资料: