分布式 session

分布式系统中,登录的 session 信息一般都是存放在 redis 中的。

本文记录一下 spring-boot 整合 redis 实现分布式 session 登录验证。

快速开始

准备工作

本地启动 redis 服务

[21496] 15 Sep 09:24:37.508 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo[21496] 15 Sep 09:24:37.510 # Redis version=5.0.9, bits=64, commit=9414ab9b, modified=0, pid=21496, just started[21496] 15 Sep 09:24:37.510 # Configuration loaded[21496] 15 Sep 09:24:37.513 # Could not create server TCP listening socket 127.0.0.1:6379: bind: 操作成功完成。
  • 进入客户端
$ redis-cli.exe127.0.0.1:6379>

此时保证 redis 中数据是空的,或者没有干扰数据:

127.0.0.1:6379> keys *(empty list or set)

基本代码

pom.xml

            org.springframework.session        spring-session                org.springframework.boot        spring-boot-starter-web                org.springframework.boot        spring-boot-starter-data-redis                            org.springframework.boot            spring-boot-maven-plugin            

目录结构

D:.├─java│  └─com│      └─github│          └─houbb│              └─spring│                  └─boot│                      └─session│                          │  Application.java│                          ││                          ├─config│                          │      HttpSessionConfig.java│                          ││                          └─controller│                                  ExampleController.java│└─resources        application.properties

后端代码

  • 启动 session
@EnableRedisHttpSessionpublic class HttpSessionConfig {}
  • Controller 示例代码
@RestControllerpublic class ExampleController {    @RequestMapping("/set")    public String set(HttpServletRequest req) {        req.getSession().setAttribute("testKey", "testValue");        return "设置session:testKey=testValue";    }    @RequestMapping("/query")    public String query(HttpServletRequest req) {        Object value = req.getSession().getAttribute("testKey");        return "查询Session:"testKey"=" + value;    }}

配置文件

主要指定 redis 的配置信息。此处为本地 redis。

spring.redis.host=127.0.0.1spring.redis.password=spring.redis.port=6379

启动测试

设置

浏览器访问 http://localhost:8080/set

页面返回:

设置session:testKey=testValue

查询

浏览器访问 http://localhost:8080/query

页面返回:

查询Session:"testKey"=testValue

信息的存储

我们看一下 Redis 中的存储信息

127.0.0.1:6379> keys *1) "spring:session:sessions:d37d1c0a-5c4a-4c60-906b-7657be1e6bc7"2) "spring:session:expirations:1600135380000"3) "spring:session:sessions:expires:d37d1c0a-5c4a-4c60-906b-7657be1e6bc7"

这是 spring-session 为我们创建的 3 个 key

我们也可以看一下对应的值

  • spring:session:sessions:d37d1c0a-5c4a-4c60-906b-7657be1e6bc7
127.0.0.1:6379> hgetall spring:session:sessions:d37d1c0a-5c4a-4c60-906b-7657be1e6bc71) "lastAccessedTime"2) "xacxedx00x05srx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x01tx8fd_xef"3) "maxInactiveInterval"4) "xacxedx00x05srx00x11java.lang.Integerx12xe2xa0xa4xf7x81x878x02x00x01Ix00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00ab"5) "sessionAttr:testKey"6) "xacxedx00x05tx00testValue"7) "creationTime"8) "xacxedx00x05srx00x0ejava.lang.Long;x8bxe4x90xccx8f#xdfx02x00x01Jx00x05valuexrx00x10java.lang.Numberx86xacx95x1dx0bx94xe0x8bx02x00x00xpx00x00x01tx8fd_xef"
  • spring:session:expirations:1600135380000
127.0.0.1:6379> smembers spring:session:expirations:16001353800001) "xacxedx00x05tx00,expires:d37d1c0a-5c4a-4c60-906b-7657be1e6bc7"
  • spring:session:sessions:expires:d37d1c0a-5c4a-4c60-906b-7657be1e6bc7
127.0.0.1:6379> get spring:session:sessions:expires:d37d1c0a-5c4a-4c60-906b-7657be1e6bc7""

基于拦截器的处理

实际开发过程中,我们肯定不希望每一次请求都自己去实现 session 的校验,查询等处理。

关于这一点,可以直接交给 mvc 的拦截器实现。

核心代码

实际上就是一个 servlet 的拦截器,每次请求获取对应的 session 信息。

这个可以基于 cookies/session/token 等等。

import org.springframework.util.StringUtils;import org.springframework.web.servlet.HandlerInterceptor;import org.springframework.web.servlet.ModelAndView;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpServletResponse;/** * @author binbin.hou * @since 1.0.0 */public class SessionInterceptor implements HandlerInterceptor {    @Override    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {        String token = httpServletRequest.getParameter("token");        String roleInfo = mockTokenResp(token);        if(StringUtils.isEmpty(roleInfo)) {            // 登录信息非法,跳转到登录页面等操作            return false;        }        // 根据信息设置等操作        return true;    }    /**     * 根据 token 去 redis 等取 session 信息,此处直接 mock 掉     * @param token 请求参数,可以是 sessionId, JWT 等     * @return 结果     */    private String mockTokenResp(String token) {        if("ryo".equals(token)) {            return "admin";        }        return "";    }    @Override    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {    }    @Override    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {    }}

小结

session 是 web 登录中必备的功能,redis 存放 session 是分布式系统中比较成熟的方案。

当然也并不是唯一的解决方案,使用 jwt 也可以达到类似的效果,不过二者各有优缺点,个人更加倾向于使用 redis 存储分布式 session。

后续有机会打开一篇讲解下 jwt 如何实现分布式系统的登录验证。

本实战系列用于记录 springboot 的实际使用和学习笔记。

希望本文对你有所帮助,如果喜欢,欢迎点赞收藏转发一波。

我是老马,期待与你的下次相遇。

spring boot 应用设置session path_springboot整合redis实现分布式session相关推荐

  1. Spring Boot(十三):整合Redis哨兵,集群模式实践

    前面的两篇文章(Redis的持久化方案, 一文掌握Redis的三种集群方案)分别介绍了Redis的持久化与集群方案 -- 包括主从复制模式.哨兵模式.Cluster模式,其中主从复制模式由于不能自动做 ...

  2. 170222、使用Spring Session和Redis解决分布式Session跨域共享问题

    使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...

  3. Spring Boot + BeetlSQL + H2数据库项目整合

    Spring Boot + BeetlSQL + H2数据库项目整合 这个项目是一个大佬给的,目的是看我的自学能力和基础知识的牢固程度,要求如下: 底层架构采用springboot 前端技术使用lay ...

  4. Spring Boot CLI设置和HelloWorld示例

    Spring Boot CLI设置和HelloWorld示例 在我之前的文章"Spring Boot简介"和"Spring Boot组件和内部"中,我们讨论了S ...

  5. SpringSession+redis解决分布式session不一致性问题

    七.案例实战:SpringSession+redis解决分布式session不一致性问题 步骤1:加入SpringSession.redis的依赖包 <dependency><gro ...

  6. 场景应用:利用Redis实现分布式Session

    文章目录 原理:Redis实现分布式Session web开发session 分布式session同步问题 分布式session解决方案 实战:Redis实现分布式Session 技术栈:Spring ...

  7. spring boot+Mybatis+mysql+atomikos+jta实现多数据源分布式事务

    spring boot+Mybatis+mysql+atomikos+jta实现多数据源分布式事务 1.导入相关依赖 2.配置相关application.properties 3.创建配置文件 4.创 ...

  8. Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session框架

    Tornado 自定义session,与一致性哈希 ,基于redis 构建分布式 session import tornado.ioloopimport tornado.webfrom myhash ...

  9. spring boot 应用设置session path_kubernetes configmap 热更新spring-boot应用

    一. 背景 在生产环境中,一个app服务处于工作中的状态,此时如果需要临时替换某些配置信息,如数据库连接池大小,链接等,一般都需要在源码端修改配置信息,然后重新部署,可想而知,这样做会影响用户或者其他 ...

  10. spring boot socket长连接_springboot 整合阿里 druid 数据库连接池实战

    情景 web 开发中连接数据库基本是必须的,阿里的 druid 是一款非常优秀的开源数据库连接池工具. 本文将介绍一下如何使用 springboot 整合 druid 数据源. 快速开始 maven ...

最新文章

  1. C++中getline()函数
  2. VMware vSphere 服务器虚拟化之二十五 桌面虚拟化之终端服务池
  3. wxWidgets:键码KeyCodes
  4. java中可重入锁的学习总结
  5. vue后端必须接口吗_前后端分离模式,后端说开发完才能给接口文档,合理吗
  6. 在线涂鸦画板小程序源码
  7. Select和epoll的区别
  8. 【ora10,4】oracle后台进程介绍:
  9. el-table固定列之后没有出现滚动条_一道经典的MySQL面试题,答案出现三次反转...
  10. mysql connector net 6.9.5_mysql connector/net6.9.5 下载 - 51下载网
  11. 关于使用skimage.measure.shannon_entropy计算图像信息熵的问题
  12. C语言十进制转换二进制
  13. 学习plc编程经验分享
  14. Web 前端页面劫持和反劫持
  15. IC卡读写器c++builder源代码续
  16. 汽车DTC故障码格式解析
  17. CAD定数等分不显示等分点
  18. 2023最新SSM计算机毕业设计选题大全(附源码+LW)之java科研信息管理503pp
  19. JAVA期末大作业之学生信息管理简洁版系统
  20. 贝叶斯分类器做文本分类案例

热门文章

  1. kafka 的经典教程
  2. BZOJ 5106 [CodePlus2017]汀博尔
  3. c# listbox使用
  4. extern 关键字详解
  5. Java直接插入排序
  6. java 判断两个时间相差的天数
  7. 【原创】Mapped Statements collection does not contain value for DaoImpl.method
  8. 强制更新客户端Silverlight XAP 文件
  9. RayTracing练习
  10. linux shell pattern,shell 三剑客之 sed pattern 详解