Session不共享问题

对于登录而言,通常情况下我们喜欢把登录信息存储到服务器的Session中,这种存储方式在单体应用中没有问题,但是在分布式/集群环境中会存在Session丢失问题,如下图:

解决方案也有很多,在《微服务认证授权方案》一文中有相关的解决方案分析,这里不在重复赘述,本文章的目的是使用SpringSession+Redis来解决分布式系统中的单点登问题

SpringSession的认证方案

这种认证方案还是使用的是session,只不过是将Session统一存储到Redis中实现session共享,各个服务可以从Redis中获取Session得到认证信息,然后做身份检查,权限校验等工作,当然整个流程我们可以自己实现,但是如何把session存储到Redis以及从Redis中取出Session是一个麻烦的事情,Spring提供了解决方案SpringSession

SpringSession干的工作就是修改getSession和setSession方法基于Redis存取Session,同时要注意的是Session是通过Cookie传递sessionid的,如果要让多个服务都能接受到sessionid拿到session,需要把cookie的存储域扩大,如有三个系统“auth.mall.com”,“goods.maill.com”,“stock.mall.com”,那我们需要把domian设置成“mall.com”,这样一来浏览器带着cookie请求任何一个系统都可以获取到sessionid,然后从Redis中获取Session。

ps:如果您还不知道session和cookie的执行流程,请先去查查资料

SpringSession入门

官网文档在这

这里我们使用SpringBoot应用为例,我们需要导入spring-session-data-redis依赖,Spring Boot 会自动创建了一个名为springSessionRepositoryFilter的Filter,它负责更换原生的HttpSession为自定义实现,比如基于Redis实现

1.搭建项目,集成SpringSession

这里是以SpringBoot为例,你需要搭建一个SpringBoot的应用,然后导入SpringSession整合Redis的依赖

    <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.0.5.RELEASE</version></parent><dependencies><dependency><groupId>org.springframework.session</groupId><artifactId>spring-session-data-redis</artifactId><exclusions><exclusion><groupId>io.lettuce</groupId><artifactId>lettuce-core</artifactId></exclusion></exclusions></dependency><dependency><groupId>redis.clients</groupId><artifactId>jedis</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency></dependencies>

data-redis默认基于lettuce实现,我这里更换成了jedis

2.配置SpringSession存储方式

然后把session配置存储类型为Redis,以及配置Redis链接信息

#server.servlet.session.timeout =#会话超时。如果未指定持续时间后缀,则使用秒。
spring:session:store-type: redisredis:host: localhostport: 6379# 选择redis的数据库的分库database: 0password: 123456#redis连接池配置jedis:pool:max-idle: 10min-idle: 5max-active: 100max-wait: 3000timeout: 6005

3.SpringSession的Java配置

最后编写SpringSesson配置类,通过@EnableRedisHttpSession 注解开启SpringSession ,通过该注解,SpringSession会创建一个Servlet过滤器,该过滤器用Spring 定义的Session替换HttpSession 实现Redis存储。

//开启SpringSession,基于Redis存储,maxInactiveIntervalInSeconds是session失效时间
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=1800)
public class SpringSessionConfig {}

注意:该配置类需要被@SpringBootApplication扫描到

4.Session存储实体类测试

实体类,需要实现Serializable接口

public class VipUser implements Serializable  {private Long id;private String password;private String nickName;...省略...
}

使用sesson存取一个User对象

@RestController
public class LoginController {@RequestMapping("/login")public void login(HttpSession session){VipUser user = new VipUser();user.setId(1L);user.setNickName("王大锤");user.setPassword("123456");String key = "user";//添加属性到Sessionsession.setAttribute(key,user);//从sesson中取出属性值VipUser userFromSession = (VipUser)session.getAttribute(key);System.out.println(userFromSession.getId()+" , "+userFromSession.getNickName()+" , "+userFromSession.getPassword());}
}

上面的代码很简单,使用session存储一个user , 启动好Redis服务器,使用Postmain访问 /login ,观察Redis中的数据

Redis效果如下:

看到这个效果,说明session确实存储到了Redis,并且可以正常的完成存取操作。

SpringSession的自定义配置

1.定义Redis序列化方式

SpringSession把值存储到Redis中默认情况下使用的是JDK的序列化方式,它要求我们存储的实体类需要实现Serializable接口,我们希望Redis以一种更友好更通用的方式去存储数据,即:JSON,我们可以通过定义序列化器来实现JSON方式的数据存储

//开启SpringSession,基于Redis存储,maxInactiveIntervalInSeconds是session失效时间
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=1800)
public class SpringSessionConfig {/*** 更换序列化器,使用JSON的序列化器*///@Bean("springSessionDefaultRedisSerializer")public RedisSerializer setSerializer(){return new GenericJackson2JsonRedisSerializer();}
}

2.定义cookie的序列化器

在前面我们讨论过,在分布式环境中,一个系统由多个子系统组成,如果要实现单点登录就要实现cookie跨域共享,否则在不同的子系统中是获取不到Session的,我们可以通过设置cookie的domain来扩大cookie的作用域,比如:有三个子系统分别是“auth.mall.com”,“goods.mall.com”,“stock.mall.com”,那么我们把cookie的domain设置为“mall.com”,那三个子系统就都可以获取到cookie,从而三个子系统都可以获取到相同的session了。

定义CookieSerializer 序列化器,如下:

//开启SpringSession,基于Redis存储,maxInactiveIntervalInSeconds是session失效时间
@EnableRedisHttpSession(maxInactiveIntervalInSeconds=1800)
public class SpringSessionConfig {/*** 更换序列化器*///@Bean("springSessionDefaultRedisSerializer")public RedisSerializer setSerializer(){return new GenericJackson2JsonRedisSerializer();}/*** 设置cookie域*/@Beanpublic CookieSerializer cookieSerializer(){DefaultCookieSerializer cookieSerializer = new DefaultCookieSerializer();//cookieSerializer.setCookieMaxAge();cookieSerializer.setCookieName("mysession");  //cookie的名字cookieSerializer.setDomainName("mall.com");        //cookie的域cookieSerializer.setUseHttpOnlyCookie(false); //只是支持httpreturn cookieSerializer;}
}

3.测试

文章结束,最后附上一张相对完整的分布式应用登录的流程图,希望对你有所帮助

十六.SpringCloud+SpringSession实现微服务单点登录相关推荐

  1. 微服务——用户微服务单点登录

    用户微服务单点登录 为什么要使用单点登录原理 链接:https://blog.csdn.net/weixin_45528987/article/details/105365115 架构图 看图可能还有 ...

  2. (十六)spring cloud微服务分布式云架构-集成项目简介

    Spring Cloud集成项目有很多,下面我们列举一下和Spring Cloud相关的优秀项目,我们的企业架构中用到了很多的优秀项目,说白了,也是站在巨人的肩膀上去整合的.在学习Spring Clo ...

  3. 微服务实战(六):选择微服务部署策略

    http://dockone.io/article/1066 微服务实战(六):选择微服务部署策略 [编者的话]这篇博客是用微服务建应用的第六篇,第一篇介绍了微服务架构模板,并且讨论了使用微服务的优缺 ...

  4. SpringCloud(若依微服务版)读取Nacos中的配置以及多个服务共享Nacos配置的使用

    场景 若依微服务版手把手教你本地搭建环境并运行前后端项目: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/109363303 在上 ...

  5. springcloud Hystrix Dashboard微服务监控

    springcloud  Hystrix Dashboard微服务监控简介 Hystrix监控 除了隔离依赖服务的调用以外,Hystrix还提供了近实时的监控,Hystrix会实时.累加地记录所有关于 ...

  6. java框架之SpringCloud(2)-Rest微服务案例

    在上一章节已经对微服务与 SpringCloud 做了介绍,为方便后面学习,下面以 Dept 部门模块为例做一个微服务通用 Demo -- Consumer 消费者(Client) 通过 REST 调 ...

  7. 【学习日记2023.6.9】之 SpringCloud入门(认识微服务_服务拆分和远程调用RestTemplate_Eureka注册中心_Ribbon负载均衡_Nacos注册中心)

    文章目录 SpringCloud 1. 认识微服务 1.1 单体架构 1.2 分布式架构 1.3 微服务 1.4 SpringCloud 1.5 总结 2. 服务拆分和远程调用 2.1 服务拆分原则 ...

  8. 若依微服务版登录流程源码分析1

    若依微服务版登录流程涉及到很多模块,本章先从网关讲起 验证码 验证码配置 先来看配置中心的网关配置文件ruoyi-gateway-dev.yml,其中有这么一段 # 安全配置 security:# 验 ...

  9. 公司账号服务单点登录到gitlab

    公司账号服务单点登录到gitlab 目标:使用oauth协议,点击挂在系统的gitlab链接,直接登录到gitlab的服务,如果没有账号则新建 操作: 一.服务端: 1.在自己的系统内添加oauth协 ...

最新文章

  1. 宏基因组文章目录(9月1日更新)
  2. 新年新气象,2008年是我创业关键的一年!
  3. 启明云端分享|SSD202D核心板使用NFS
  4. Myeclipse快捷键总结大全
  5. lua jit java jit_Lua JIT 2.0 发布了,一百五十倍的性能提升!
  6. android 调用系统自带文件管理器_编写使用Android 系统自带的文字转语音代码
  7. 1命名规则 sentinel_Sentinel实战:为系统做限流保护
  8. springmvc获取url对应的controller,并拦截记录每次访问的controller方法
  9. Python Prep随想练习-Day3
  10. 左手鼠标指针_使您的鼠标指针左手友好
  11. 不打开Excel文件读取工作表名(ADOX)
  12. Color correction matrix(色彩矩阵)的学习思考
  13. Google、Facebook的工程师文化到底是什么?
  14. react 组件构建_为React构建星级评定组件
  15. Could not find a getter for name in class org.tarena.entity1.City
  16. 洗牌前夜:中国云主机市场全景观察
  17. 2023年华数杯国际赛数学建模
  18. STM32和树莓派串口透传
  19. win10系统怎么启用策略服务器,Windows 10系统启动项安全引导策略
  20. 最小环问题(无向图)

热门文章

  1. c语言斜线方程,切线方程公式
  2. 基于JAVA的地铁订票系统
  3. 一致性(Consistency),可用性(Avilable),分区容错性(Tolerance of network Partition)
  4. python 在日常工作中_每天在工作和生活中做的事,我如何用 Python 让它们变得更轻松?...
  5. 【视频】国产电子核混音|Lost In Summer - Release The Soul |混音母带处理 by JeromeAlanChan
  6. 魅族16php7.3系统,魅族16th Plus官方固件rom系统刷机包:稳定版7.3.0.0A
  7. 魅族系统底层更新鸿蒙吗,魅族工程师回复网友:Flyme 8没有升级底层
  8. emlog高仿小刀新版本模板
  9. IT互联网行业各岗位介绍及知识普及
  10. java ssm开发酒店管理,Ssm+Mysql实现的Java Web酒店管理系统毕设指导思路模板