十六.SpringCloud+SpringSession实现微服务单点登录
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实现微服务单点登录相关推荐
- 微服务——用户微服务单点登录
用户微服务单点登录 为什么要使用单点登录原理 链接:https://blog.csdn.net/weixin_45528987/article/details/105365115 架构图 看图可能还有 ...
- (十六)spring cloud微服务分布式云架构-集成项目简介
Spring Cloud集成项目有很多,下面我们列举一下和Spring Cloud相关的优秀项目,我们的企业架构中用到了很多的优秀项目,说白了,也是站在巨人的肩膀上去整合的.在学习Spring Clo ...
- 微服务实战(六):选择微服务部署策略
http://dockone.io/article/1066 微服务实战(六):选择微服务部署策略 [编者的话]这篇博客是用微服务建应用的第六篇,第一篇介绍了微服务架构模板,并且讨论了使用微服务的优缺 ...
- SpringCloud(若依微服务版)读取Nacos中的配置以及多个服务共享Nacos配置的使用
场景 若依微服务版手把手教你本地搭建环境并运行前后端项目: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/109363303 在上 ...
- springcloud Hystrix Dashboard微服务监控
springcloud Hystrix Dashboard微服务监控简介 Hystrix监控 除了隔离依赖服务的调用以外,Hystrix还提供了近实时的监控,Hystrix会实时.累加地记录所有关于 ...
- java框架之SpringCloud(2)-Rest微服务案例
在上一章节已经对微服务与 SpringCloud 做了介绍,为方便后面学习,下面以 Dept 部门模块为例做一个微服务通用 Demo -- Consumer 消费者(Client) 通过 REST 调 ...
- 【学习日记2023.6.9】之 SpringCloud入门(认识微服务_服务拆分和远程调用RestTemplate_Eureka注册中心_Ribbon负载均衡_Nacos注册中心)
文章目录 SpringCloud 1. 认识微服务 1.1 单体架构 1.2 分布式架构 1.3 微服务 1.4 SpringCloud 1.5 总结 2. 服务拆分和远程调用 2.1 服务拆分原则 ...
- 若依微服务版登录流程源码分析1
若依微服务版登录流程涉及到很多模块,本章先从网关讲起 验证码 验证码配置 先来看配置中心的网关配置文件ruoyi-gateway-dev.yml,其中有这么一段 # 安全配置 security:# 验 ...
- 公司账号服务单点登录到gitlab
公司账号服务单点登录到gitlab 目标:使用oauth协议,点击挂在系统的gitlab链接,直接登录到gitlab的服务,如果没有账号则新建 操作: 一.服务端: 1.在自己的系统内添加oauth协 ...
最新文章
- 宏基因组文章目录(9月1日更新)
- 新年新气象,2008年是我创业关键的一年!
- 启明云端分享|SSD202D核心板使用NFS
- Myeclipse快捷键总结大全
- lua jit java jit_Lua JIT 2.0 发布了,一百五十倍的性能提升!
- android 调用系统自带文件管理器_编写使用Android 系统自带的文字转语音代码
- 1命名规则 sentinel_Sentinel实战:为系统做限流保护
- springmvc获取url对应的controller,并拦截记录每次访问的controller方法
- Python Prep随想练习-Day3
- 左手鼠标指针_使您的鼠标指针左手友好
- 不打开Excel文件读取工作表名(ADOX)
- Color correction matrix(色彩矩阵)的学习思考
- Google、Facebook的工程师文化到底是什么?
- react 组件构建_为React构建星级评定组件
- Could not find a getter for name in class org.tarena.entity1.City
- 洗牌前夜:中国云主机市场全景观察
- 2023年华数杯国际赛数学建模
- STM32和树莓派串口透传
- win10系统怎么启用策略服务器,Windows 10系统启动项安全引导策略
- 最小环问题(无向图)
热门文章
- c语言斜线方程,切线方程公式
- 基于JAVA的地铁订票系统
- 一致性(Consistency),可用性(Avilable),分区容错性(Tolerance of network Partition)
- python 在日常工作中_每天在工作和生活中做的事,我如何用 Python 让它们变得更轻松?...
- 【视频】国产电子核混音|Lost In Summer - Release The Soul |混音母带处理 by JeromeAlanChan
- 魅族16php7.3系统,魅族16th Plus官方固件rom系统刷机包:稳定版7.3.0.0A
- 魅族系统底层更新鸿蒙吗,魅族工程师回复网友:Flyme 8没有升级底层
- emlog高仿小刀新版本模板
- IT互联网行业各岗位介绍及知识普及
- java ssm开发酒店管理,Ssm+Mysql实现的Java Web酒店管理系统毕设指导思路模板