Spring Security怎么处理Session 共享

技术Spring Security怎么处理Session 共享这篇文章主要介绍“Spring Security怎么处理Session 共享”,在日常操作中,相信很多人在Spring Security怎么处理Session

本文主要介绍“Spring Security如何处理会话共享”。在日常操作中,我相信很多人对Spring Security如何处理Session共享有疑问。边肖查阅了各种资料,整理出简单易用的操作方法,希望能帮你解答“Spring Security如何处理Session共享”的疑惑!接下来,请和边肖一起学习!

1.集群会话方案

在传统的单一服务架构中,一般来说只有一个服务器,所以不存在Session共享的问题。然而,在分布式/集群项目中,会话共享是必须面对的问题。首先,看一个简单的架构图:

Spring  Security怎么处理Session  共享

在这种架构下,会出现一些单一服务不存在的问题,比如客户端发起请求,请求到达Nginx后,由Nginx转发给Tomcat A,然后在Tomcat A上的session中保存一段数据,下一次向Tomcat B发送请求,此时发现Session中没有之前的数据。

1.1 session 共享

目前这类问题的主流解决方案是将需要在各种服务之间共享的数据保存在公共场所(主流解决方案是Redis):

Spring  Security怎么处理Session  共享

当所有Tomcat需要将数据写入Session时,它们都写入Redis,当所有Tomcat需要读取数据时,它们都从Redis读取。这样,不同的服务可以使用相同的会话数据。

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

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

对于开发人员来说,所有关于会话同步的操作都是透明的。开发人员使用春季会议。一旦配置完成,具体用法就像使用普通会话一样。

1.2 session 拷贝

会话复制是不使用redis直接在Tomcats之间复制会话数据,但是这种方法效率有点低。Tomcat A、B和C的任何会话都已更改,需要复制到其他Tomcat。如果集群中的服务器数量特别多,这种方法不仅效率低,而且延迟严重。

因此,这种方案一般可以视为理解。

1.3 粘滞会话

所谓粘性会话,就是把来自同一个IP的请求通过Nginx路由到同一个Tomcat,这样就不需要会话共享和同步了。这是一种解决方案,但在某些极端情况下,可能会导致负载不平衡(因为大多数情况下,许多人使用相同的公共IP)。

因此,会话共享成为解决这一问题的主流方案。

2.Session共享

2.1 创建工程

首先,创建一个Spring Boot项目,介绍Web、春季会议、春季安全和Redis:

Spring  Security怎么处理Session  共享

成功创建后,pom.xml文件如下所示:

dependencygroupidgor . spring framework . boot/group idartifactidspring-boot-starter-data-redis/artifactId/dependency dependency cynbs

p;   <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency>     <groupId>org.springframework.session</groupId>     <artifactId>spring-session-data-redis</artifactId> </dependency>

2.2 配置

spring.redis.password=123 spring.redis.port=6379 spring.redis.host=127.0.0.1  spring.security.user.name=javaboy spring.security.user.password=123  server.port=8080

配置一下 Redis 的基本信息;Spring Security 为了简化,我就将用户名密码直接配置在 application.properties  中了,最后再配置一下项目端口号。

2.3 使用

配置完成后 ,就可以使用 Spring Session 了,其实就是使用普通的 HttpSession ,其他的 Session 同步到 Redis  等操作,框架已经自动帮你完成了:

@RestController public class HelloController {     @Value("${server.port}")     Integer port;     @GetMapping("/set")     public String set(HttpSession session) {         session.setAttribute("user", "javaboy");         return String.valueOf(port);     }     @GetMapping("/get")     public String get(HttpSession session) {         return session.getAttribute("user") + ":" + port;     } }

考虑到一会 Spring Boot 将以集群的方式启动 ,为了获取每一个请求到底是哪一个 Spring Boot  提供的服务,需要在每次请求时返回当前服务的端口号,因此这里我注入了 server.port 。

接下来 ,项目打包:

Spring Security怎么处理Session 共享

打包之后,启动项目的两个实例:

java -jar session-4-0.0.1-SNAPSHOT.jar --server.port=8080 java -jar session-4-0.0.1-SNAPSHOT.jar --server.port=8081

然后先访问 localhost:8080/set 向 8080 这个服务的 Session  中保存一个变量,第一次访问时会自动跳转到登录页面,输入用户名密码进行登录即可。访问成功后,数据就已经自动同步到 Redis 中 了 :

Spring Security怎么处理Session 共享

然后,再调用 localhost:8081/get 接口,就可以获取到 8080 服务的 session 中的数据:

Spring Security怎么处理Session 共享

此时关于 session 共享的配置就已经全部完成了,session 共享的效果我们已经看到了。

2.4 Security 配置

Session 共享已经实现了,但是我们发现新的问题,在Spring Boot + Vue 前后端分离项目,如何踢掉已登录用户?一文中我们配置的  session 并发管理失效了。

也就是说,如果我添加了如下配置:

protected void configure(HttpSecurity http) throws Exception {     http.authorizeRequests().anyRequest()             ...             .sessionManagement()             .maximumSessions(1)             .maxSessionsPreventsLogin(true); }

现在这个配置不起作用,用户依然可以在多个浏览器上同时登录。

这是怎么回事呢?

在该文中,我们提到,会话注册表的维护默认是由 SessionRegistryImpl 来维护的,而 SessionRegistryImpl  的维护就是基于内存的维护。现在我们虽然启用了 Spring Session+Redis 做 Session 共享,但是 SessionRegistryImpl  依然是基于内存来维护的,所以我们要修改 SessionRegistryImpl 的实现逻辑。

修改方式也很简单,实际上 Spring Session 为我们提供了对应的实现类  SpringSessionBackedSessionRegistry,具体配置如下:

@Configuration public class SecurityConfig extends WebSecurityConfigurerAdapter {     @Autowired     FindByIndexNameSessionRepository sessionRepository;     @Override     protected void configure(HttpSecurity http) throws Exception {         http.authorizeRequests().anyRequest()                 ...                 .sessionManagement()                 .maximumSessions(1)                 .maxSessionsPreventsLogin(true)                 .sessionRegistry(sessionRegistry());     }     @Bean     SpringSessionBackedSessionRegistry sessionRegistry() {         return new SpringSessionBackedSessionRegistry(sessionRepository);     } }

我们在这里只需要提供一个 SpringSessionBackedSessionRegistry 的实例,并且将其配置到 sessionManagement  中去即可。以后,session 并发数据的维护将由 SpringSessionBackedSessionRegistry 来完成,而不是  SessionRegistryImpl,如此,我们关于 session 并发的配置就生效了,在集群环境下,用户也只可以在一台设备上登录。

为了让我们的案例看起更完美一些,接下来我们来引入 Nginx ,实现服务实例自动切换。

3.引入 Nginx

很简单,进入 Nginx 的安装目录的 conf 目录下(默认是在/usr/local/nginx/conf),编辑  nginx.conf 文件:

Spring Security怎么处理Session 共享

在这段配置中:

  1. upstream 表示配置上游服务器

  2. javaboy.org 表示服务器集群的名字,这个可以随意取名字

  3. upstream 里边配置的是一个个的单独服务

  4. weight 表示服务的权重,意味者将有多少比例的请求从 Nginx 上转发到该服务上

  5. location 中的 proxy_pass 表示请求转发的地址,/ 表示拦截到所有的请求,转发转发到刚刚配置好的服务集群中

  6. proxy_redirect 表示设置当发生重定向请求时,nginx 自动修正响应头数据(默认是 Tomcat 返回重定向,此时重定向的地址是  Tomcat 的地址,我们需要将之修改使之成为 Nginx 的地址)。

配置完成后,将本地的 Spring Boot 打包好的 jar 上传到 Linux ,然后在 Linux 上分别启动两个 Spring Boot  实例:

nohup java -jar session-4-0.0.1-SNAPSHOT.jar --server.port=8080 & nohup java -jar session-4-0.0.1-SNAPSHOT.jar --server.port=8081 &

其中

  • nohup 表示当终端关闭时,Spring Boot 不要停止运行

  • & 表示让 Spring Boot 在后台启动

配置完成后,重启 Nginx:

/usr/local/nginx/sbin/nginx -s reload

Nginx 启动成功后,我们首先手动清除 Redis 上的数据,然后访问192.168.66.128/set 表示向 session  中保存数据,这个请求首先会到达 Nginx 上,再由 Nginx 转发给某一个 Spring Boot 实例:

Spring Security怎么处理Session 共享

如上,表示端口为 8081 的 Spring Boot 处理了这个 /set 请求,再访问 /get 请求:

Spring Security怎么处理Session 共享

可以看到,/get 请求是被端口为 8080 的服务所处理的。

到此,关于“Spring Security怎么处理Session 共享”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注网站,小编会继续努力为大家带来更多实用的文章!

内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/90607.html

(1)

相关推荐

  • 中国十大名牌大学排名,中国十大名牌大学是哪十所

    技术中国十大名牌大学排名,中国十大名牌大学是哪十所根据2018最新中国双一流大学排名中国十大名牌大学排名,前十所大学分别是:北京大学清华大学
    浙江大学
    复旦大学
    中国人民大学
    上海交通大学
    武汉大学
    南京大学
    中山大学

    生活 2021年10月31日
  • 纸牌游戏程序设计(用c语言做卡牌游戏教程)

    技术怎样用C语言实现纸牌游戏今天就跟大家聊聊有关怎样用C语言实现纸牌游戏,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。1. 基本要求一副没有花牌(J、Q、K、A、

    攻略 2021年12月18日
  • 如何解决PHP xcache无法加载

    技术如何解决PHP xcache无法加载这篇文章主要讲解了“如何解决PHP xcache无法加载”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何解决PHP xcache

    攻略 2021年10月23日
  • google的数据分析用的什么(google analytics分析证书含金量)

    技术替代Google Analytics的轻量级分析工具是什么本篇文章给大家分享的是有关替代Google Analytics的轻量级分析工具是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收

    攻略 2021年12月16日
  • 怎么用Go实现字符串逆序

    技术怎么用Go实现字符串逆序怎么用Go实现字符串逆序,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。使用Go来实现字符串逆序这个功能,用最简单的话术让你理解

    攻略 2021年11月15日
  • 如何理解IDEA 的项目配置和Web部署

    技术如何理解IDEA 的项目配置和Web部署这篇文章将为大家详细讲解有关如何理解IDEA 的项目配置和Web部署,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。作者:Dul

    攻略 2021年11月18日