Spring Security 要怎么处理 session 共享?

今天我们就来看看集群化部署,Spring Security 要如何处理 session 并发。

1.集群会话方案

在传统的单服务架构中,一般来说,只有一个服务器,那么不存在 Session 共享问题,但是在分布式/集群项目中,Session 共享则是一个必须面对的问题,先看一个简单的架构图:

在这样的架构中,会出现一些单服务中不存在的问题,例如客户端发起一个请求,这个请求到达 Nginx 上之后,被 Nginx 转发到 Tomcat A 上,然后在 Tomcat A 上往 session 中保存了一份数据,下次又来一个请求,这个请求被转发到 Tomcat B  上,此时再去 Session 中获取数据,发现没有之前的数据。

1.1 session 共享

对于这一类问题的解决,目前比较主流的方案就是将各个服务之间需要共享的数据,保存到一个公共的地方(主流方案就是 Redis):

当所有 Tomcat 需要往 Session 中写数据时,都往 Redis 中写,当所有 Tomcat 需要读数据时,都从 Redis 中读。这样,不同的服务就可以使用相同的 Session 数据了。

这样的方案,可以由开发者手动实现,即手动往 Redis 中存储数据,手动从 Redis 中读取数据,相当于使用一些 Redis 客户端工具来实现这样的功能,毫无疑问,手动实现工作量还是蛮大的。

一个简化的方案就是使用 Spring Session 来实现这一功能,Spring Session 就是使用 Spring 中的代理过滤器,将所有的 Session 操作拦截下来,自动的将数据 同步到 Redis 中,或者自动的从 Redis 中读取数据。

对于开发者来说,所有关于 Session 同步的操作都是透明的,开发者使用 Spring Session,一旦配置完成后,具体的用法就像使用一个普通的 Session 一样。

1.2 session 拷贝

session 拷贝就是不利用 redis,直接在各个 Tomcat 之间进行 session 数据拷贝,但是这种方式效率有点低,Tomcat A、B、C 中任意一个的 session 发生了变化,都需要拷贝到其他 Tomcat 上,如果集群中的服务器数量特别多的话,这种方式不仅效率低,还会有很严重的延迟。

所以这种方案一般作为了解即可。

1.3 粘滞会话

所谓的粘滞会话就是将相同 IP 发送来的请求,通过 Nginx 路由到同一个 Tomcat 上去,这样就不用进行 session 共享与同步了。这是一个办法,但是在一些极端情况下,可能会导致负载失衡(因为大部分情况下,都是很多人用同一个公网 IP)。

所以,Session 共享就成为了这个问题目前主流的解决方案了。

2.Session共享

2.1 创建工程

首先 创建一个 Spring Boot 工程,引入 Web、Spring Session、Spring Security 以及 Redis:

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Spring Security中实现Session共享有多种方式,可以使用分布式缓存、数据库存储或使用单点登录(Single Sign-On)等方式。下面我将介绍一种常见的方法,即使用分布式缓存实现Session共享。 一、配置分布式缓存 1. 首先,您需要选择一个适合您的分布式缓存解决方案,比如Redis或Memcached。 2. 根据您选择的分布式缓存,添加相应的依赖到项目中,并配置缓存服务器的连接信息。 二、配置Spring Security 1. 创建一个自定义的SessionRegistry实现类,用于管理会话信息。该类可以使用缓存来存储和获取会话数据。您可以实现SessionRegistry接口,并使用分布式缓存来实现相关的方法。 2. 在Spring Security的配置类中添加以下代码: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SessionRegistry sessionRegistry; @Override protected void configure(HttpSecurity http) throws Exception { http .sessionManagement() .maximumSessions(-1) .sessionRegistry(sessionRegistry) .and() .invalidSessionUrl("/login?expired") .and() // 其他的安全配置... } @Bean public HttpSessionEventPublisher httpSessionEventPublisher() { return new HttpSessionEventPublisher(); } } ``` 三、配置会话管理器 1. 创建一个自定义的会话管理器,并注入SessionRegistry实例。 例如,可以创建一个名为CustomConcurrentSessionControlStrategy的类,并实现ConcurrentSessionControlStrategy接口: ```java @Component public class CustomConcurrentSessionControlStrategy extends ConcurrentSessionControlStrategy { public CustomConcurrentSessionControlStrategy(SessionRegistry sessionRegistry) { super(sessionRegistry); } } ``` 2. 在Spring Security的配置类中添加以下代码: ```java @Configuration @EnableWebSecurity public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private SessionRegistry sessionRegistry; @Autowired private CustomConcurrentSessionControlStrategy customConcurrentSessionControlStrategy; @Override protected void configure(HttpSecurity http) throws Exception { http .sessionManagement() .maximumSessions(-1) .sessionRegistry(sessionRegistry) .sessionAuthenticationErrorUrl("/login?expired") .and() .invalidSessionUrl("/login?expired") .and() // 其他的安全配置... } @Bean public HttpSessionEventPublisher httpSessionEventPublisher() { return new HttpSessionEventPublisher(); } @Bean public SessionRegistry sessionRegistry() { return new SessionRegistryImpl(); } @Bean public CustomConcurrentSessionControlStrategy customConcurrentSessionControlStrategy(SessionRegistry sessionRegistry) { return new CustomConcurrentSessionControlStrategy(sessionRegistry); } } ``` 通过以上配置,您可以启用会话共享并使用分布式缓存来存储和管理会话信息。请根据您的需求进行相应的调整和修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值