spring security 会话管理

2024-08-31 19:36

本文主要是介绍spring security 会话管理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、简介

    当浏览器调用登录接口登录成功后,服务端会和浏览器之间建立一个会话(Session)浏览器在每次发送请求时都会携带一个 Sessionld,服务端则根据这个 Sessionld 来判断用户身份当浏览器关闭后,服务端的 Session 并不会自动销毁,需要开发者手动在服务端调用Session销毁方法,或者等 Session 过期时间到了自动销毁。在Spring Security 中,与HttpSession相关的功能由 SessionManagemenFiter 和Session AutheaticationStrateey 接口来处理,SessionManagomentFilter 过滤器将Session 相关操作委托给SessionAuthenticationStrategy 接口去完成。

二、会话并发管理

   会话并发管理就是指在当前系统中,同一个用户可以同时创建多少个会话,如果一合设备对应一个会话,那么也可以简单理解为同一个用户可以同时在多少台设备上进行登录。默认情况下,同一用户在多少台设备上登录并没有限制,不过开发者可以在 Spring Security 中对此进行配置。

2.1 开启会话管理

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {/*** 自定义数据源,从内存中,后期自己写一个mybatis 从数据库查询* @throws Exception{scrypt}*/@Beanpublic UserDetailsService userDetailsService() {InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();userDetailsManager.createUser(User.withUsername("admin").password("{noop}12345").authorities("admin").build());return userDetailsManager;}/***  自定义authenticationManager 管理器,将自定义的数据源加到其中* @throws Exception*/@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userDetailsService());}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin()// 表单登录.loginProcessingUrl("/doLogin").and().csrf().disable().sessionManagement()// 开启会管理.maximumSessions(1); //设置会话并发数为1}@Beanpublic HttpSessionEventPublisher httpSessionEventPublisher() {return new HttpSessionEventPublisher();}}
  1. sessionManagement)用来开启会话管理、maximumSessions指定会话的并发数为1。
  2. HttpSessionEventPublisher提供一一个Htp SessionEvenePubishor-实例。Spring Security中通过一个 Map 集合来集护当前的 Http Session 记录,进而实现会话的并发管理。当用户登录成功时,就向集合中添加一条Http Session 记录;当会话销毁时,就从集合中移除一条Httpsession 记录。HtpSesionEvenPublisher 实现了 Fttp SessionListener 接口,可以监听到 HtpSession 的创建和销毁事件,并将 Fltp Session 的创建/销毁事件发布出去,这样,当有 HttpSession 销毁时,Spring Security 就可以感知到该事件了。

2.2 测试会话管理

     配置完成后,启动项目。这次测试我们需要两个浏览器,如果使用了 Chrome 浏览器,可以使用 Chrome浏览器中的多用户方式(相当于两个浏览器)先在第一个浏览器中输入 http://localhost:8081,此时会自动跳转到登录页面,完成登录操作,就可以访问到数据了;接下来在第二个浏览器中也输入 http://localhost:8081,也需要登录完成登录操作;当第二个浏览器登录成功后,再回到第一个浏览器,刷新页面。结果出现下当另外一个浏览器登录后,就把前一个会话挤掉线了;

2.3 会话失效处理(传统web)

protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin()// 表单登录.loginProcessingUrl("/doLogin").and().csrf().disable().sessionManagement()// 开启会管理.maximumSessions(1) //设置会话并发数为1.expiredUrl("/login"); // 会话过期跳转页面}

这次会话失效后,就会跳到登录页面了,就不会出现这个英文提示了;

2.4 会话失效处理(前后端分离实现)

@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin()// 表单登录.loginProcessingUrl("/doLogin").and().csrf().disable().sessionManagement()// 开启会管理.maximumSessions(1) //设置会话并发数为1//.expiredUrl("/login"); // 会话过期跳转页面.expiredSessionStrategy(ses -> {HttpServletResponse response = ses.getResponse();Map<String,String> resMap = new HashMap<>();resMap.put("code","5001");resMap.put("msg","你的账号已经挤下线了,请重新登录!");String resStr = new ObjectMapper().writeValueAsString(resMap);response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);response.getWriter().println(resStr);});}

2.5 禁止再此登录

    默认的效果是一种被“挤下线”的效果,后面登录的用户会把前面登录的用户“挤下线。还有一种是禁止后来者登录,即一旦当前用户登录成功,后来者无法再次使用相同的用户登录,直到当前用户主动注销登录,配置如下:

@Override
protected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin()// 表单登录.loginProcessingUrl("/doLogin")// 退出登录.and().logout().and().csrf().disable().sessionManagement()// 开启会管理.maximumSessions(1) //设置会话并发数为1//.expiredUrl("/login"); // 会话过期跳转页面.expiredSessionStrategy(ses -> {HttpServletResponse response = ses.getResponse();Map<String,String> resMap = new HashMap<>();resMap.put("code","5001");resMap.put("msg","你的账号已经挤下线了,请重新登录!");String resStr = new ObjectMapper().writeValueAsString(resMap);response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);response.getWriter().println(resStr);response.flushBuffer();}).maxSessionsPreventsLogin(true);// 一旦登录  禁止后来其它账号登录}


三、会话共享

    前面所讲的会话管理都是单机上的会话管理,也就是在单体架构,如果当前是集群环境,前面所讲的会话管理方案就会失效。此时可以利用 spring-session 结合 redis 实现 session 共享。

3.1 引入依赖

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

3.2 代码配置

@Autowired
private RedisTemplate redisTemplate;@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin()// 表单登录.loginProcessingUrl("/doLogin")// 退出登录.and().logout().and().csrf().disable().sessionManagement()// 开启会管理.maximumSessions(1) //设置会话并发数为1//.expiredUrl("/login"); // 会话过期跳转页面.expiredSessionStrategy(ses -> {HttpServletResponse response = ses.getResponse();Map<String,String> resMap = new HashMap<>();resMap.put("code","5001");resMap.put("msg","你的账号已经挤下线了,请重新登录!");String resStr = new ObjectMapper().writeValueAsString(resMap);response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);response.getWriter().println(resStr);response.flushBuffer();})//.maxSessionsPreventsLogin(true);// 一旦登录  禁止后来其它账号登录.sessionRegistry(sessionRegistry());// 将session 交给谁管理}// 创建session 同步到redis中方案
@Bean
public SpringSessionBackedSessionRegistry sessionRegistry() {FindByIndexNameSessionRepository indexNameSessionRepository = new RedisIndexedSessionRepository(redisTemplate);return new SpringSessionBackedSessionRegistry(indexNameSessionRepository);
}

最终查看redis结果

这篇关于spring security 会话管理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1124812

相关文章

SpringBoot使用Apache Tika检测敏感信息

《SpringBoot使用ApacheTika检测敏感信息》ApacheTika是一个功能强大的内容分析工具,它能够从多种文件格式中提取文本、元数据以及其他结构化信息,下面我们来看看如何使用Ap... 目录Tika 主要特性1. 多格式支持2. 自动文件类型检测3. 文本和元数据提取4. 支持 OCR(光学

Java内存泄漏问题的排查、优化与最佳实践

《Java内存泄漏问题的排查、优化与最佳实践》在Java开发中,内存泄漏是一个常见且令人头疼的问题,内存泄漏指的是程序在运行过程中,已经不再使用的对象没有被及时释放,从而导致内存占用不断增加,最终... 目录引言1. 什么是内存泄漏?常见的内存泄漏情况2. 如何排查 Java 中的内存泄漏?2.1 使用 J

JAVA系统中Spring Boot应用程序的配置文件application.yml使用详解

《JAVA系统中SpringBoot应用程序的配置文件application.yml使用详解》:本文主要介绍JAVA系统中SpringBoot应用程序的配置文件application.yml的... 目录文件路径文件内容解释1. Server 配置2. Spring 配置3. Logging 配置4. Ma

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

java脚本使用不同版本jdk的说明介绍

《java脚本使用不同版本jdk的说明介绍》本文介绍了在Java中执行JavaScript脚本的几种方式,包括使用ScriptEngine、Nashorn和GraalVM,ScriptEngine适用... 目录Java脚本使用不同版本jdk的说明1.使用ScriptEngine执行javascript2.

Spring MVC如何设置响应

《SpringMVC如何设置响应》本文介绍了如何在Spring框架中设置响应,并通过不同的注解返回静态页面、HTML片段和JSON数据,此外,还讲解了如何设置响应的状态码和Header... 目录1. 返回静态页面1.1 Spring 默认扫描路径1.2 @RestController2. 返回 html2

Spring常见错误之Web嵌套对象校验失效解决办法

《Spring常见错误之Web嵌套对象校验失效解决办法》:本文主要介绍Spring常见错误之Web嵌套对象校验失效解决的相关资料,通过在Phone对象上添加@Valid注解,问题得以解决,需要的朋... 目录问题复现案例解析问题修正总结  问题复现当开发一个学籍管理系统时,我们会提供了一个 API 接口去

Java操作ElasticSearch的实例详解

《Java操作ElasticSearch的实例详解》Elasticsearch是一个分布式的搜索和分析引擎,广泛用于全文搜索、日志分析等场景,本文将介绍如何在Java应用中使用Elastics... 目录简介环境准备1. 安装 Elasticsearch2. 添加依赖连接 Elasticsearch1. 创

Spring核心思想之浅谈IoC容器与依赖倒置(DI)

《Spring核心思想之浅谈IoC容器与依赖倒置(DI)》文章介绍了Spring的IoC和DI机制,以及MyBatis的动态代理,通过注解和反射,Spring能够自动管理对象的创建和依赖注入,而MyB... 目录一、控制反转 IoC二、依赖倒置 DI1. 详细概念2. Spring 中 DI 的实现原理三、

SpringBoot 整合 Grizzly的过程

《SpringBoot整合Grizzly的过程》Grizzly是一个高性能的、异步的、非阻塞的HTTP服务器框架,它可以与SpringBoot一起提供比传统的Tomcat或Jet... 目录为什么选择 Grizzly?Spring Boot + Grizzly 整合的优势添加依赖自定义 Grizzly 作为