当前位置: 首页 > news >正文

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结果


http://www.mrgr.cn/news/16402.html

相关文章:

  • 如何打开终端?
  • 06:网表更新到PCB
  • macOS搭建Python3.11+Django4.2.15的平台框架使用Poetry管理
  • 最新版 Java 网络编程|万字笔记
  • Linux学习(17)-I/O复用(1)select、poll
  • BUUCTF PWN wp--jarvisoj_level0
  • 4.负载均衡
  • 可以根据手机的折叠状态改变播放音效:nova Flip 的妙趣音效
  • C# 开发环境搭建(Avalonia UI、Blazor Web UI、Web API 应用示例)
  • 报错记录2:imx6ull适配ov2640摄像头查询不到分辨率大小
  • Linux——命令行文件的管理(创建,复制,删除,移动文件,硬链接与软链接)
  • JUC-JAVA内存模型
  • Java面试题真题·技术面试题部分总结
  • 平台介绍-机构、岗位、人员基础数据
  • 有宠物用哪个牌子的宠物空气净化器,希喂、IAM哪个更值得推荐
  • 【3D目标检测】MMdetection3d——nuScenes数据集训练BEVFusion
  • ubuntu24下python3.9安装pytorch
  • 和星辰为伴,与代码共舞
  • 【Centos】yum 安装软件失败时,切换 Aliyun 镜像源
  • 【Kubernetes部署篇】二进制搭建K8s高可用集群1.26.15版本