爆破专栏丨Spring Security系列教程之会话管理之会话并发控制_springboot限制一个页面出现两个会话(1)

先自我介绍一下,小编浙江大学毕业,去过华为、字节跳动等大厂,目前阿里P7

深知大多数程序员,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年最新网络安全全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友。
img
img
img
img
img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上网络安全知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以添加V获取:vip204888 (备注网络安全)
img

正文

请各位带着以上的这些问题,跟着 一一哥 继续往下学习吧。

需要更多教程,微信扫码即可

👆👆👆

别忘了扫码领资料哦【高清Java学习路线图

全套学习视频及配套资料****

一. 会话并发控制

  1. 会话并发控制

首先我们来了解一下会话并发控制的概念。

有时候出于安全的目的,我们可能会有这样的需求,就是规定在同一个系统中,只允许一个用户在一个终端上登录,这其实就是对会话的并发控制。

  1. 并发控制实现思路

如果我们要想上述目标,即同一个用户不能同时在两台设备上登录,我们有两种解决思路:

  • 后来的登录自动踢掉前面的登录,例如QQ。

  • 如果用户已经登录,则不允许后来者登录。

以上两种思路都能实现这个功能,具体使用哪一个,还要看我们具体的需求。在 Spring Security 框架中,这两种思路都很容易实现,一个配置就可以搞定。

  1. 实现方案一:踢掉原有登录用户

我们可以在SecurityConfig配置类中,通过maximumSessions()方法来置单个用户允许同时在线的最大并发会话数,如果没有额外配置,重新登录的会话会踢掉旧的会话。

@EnableWebSecurity(debug = **true**)
**public** **class** **SecurityConfig** **extends** **WebSecurityConfigurerAdapter** {

    @Override
    **protected** **void** **configure**(HttpSecurity http) **throws** Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**")
                .hasRole("ADMIN")
                .antMatchers("/user/**")
                .hasRole("USER")
                .antMatchers("/app/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable()
                .formLogin()
                .permitAll()
                .and()
                //进行会话管理
                .sessionManagement()
                //最大并发会话数,设置单个用户允许同时在线的最大会话数,如果没有额外配置,重新登录的会话会踢掉旧的会话.
                .maximumSessions(1);
    }

    @Bean
    **public** PasswordEncoder **passwordEncoder**() {

        **return** NoOpPasswordEncoder.getInstance();
    }

}

**maximum Sessions: 表示最大并发会话数,设置单个用户允许同时在线的最大会话数,如果没有额外配置,重新登录的会话会踢掉旧的会话。**这里配置最大会话数为 1,这样后面的登录就会自动踢掉前面的登录。

配置完成后,分别用 Chrome 和 Firefox 两个浏览器进行测试(或者使用 Chrome 中的多用户功能)。

  • 我们先在Firefox 上访问 /user/hello 接口。

  • 然后在Chrome 上访问 /user/hello 接口。

等我们在 Firefox 上再次访问 /user/hello 接口时,此时会看到如下提示:

图片

以上信息表明第一个 session 已经过期,原因则是由于使用同一个用户进行并发登录。

  1. 实现方案二:阻止新用户登录

如果我们已经有一个用户登录了,这时候这个相同的账号信息还想再次登录,我们可以阻止新用户登录,配置方式如下:

@EnableWebSecurity(debug = **true**)
**public** **class** **SecurityConfig** **extends** **WebSecurityConfigurerAdapter** {

    @Override
    **protected** **void** **configure**(HttpSecurity http) **throws** Exception {
        http.authorizeRequests()
                .antMatchers("/admin/**")
                .hasRole("ADMIN")
                .antMatchers("/user/**")
                .hasRole("USER")
                .antMatchers("/app/**")
                .permitAll()
                .anyRequest()
                .authenticated()
                .and()
                .csrf()
                .disable()
                .formLogin()
                .permitAll()
                .and()
                //进行会话管理
                .sessionManagement()
                //最大并发会话数,设置单个用户允许同时在线的最大会话数,如果没有额外配置,重新登录的会话会踢掉旧的会话.
                .maximumSessions(1)
                //当达到最大会话数时,阻止建立新会话,而不是踢掉旧的会话.默认为false
                .maxSessionsPreventsLogin(**true**);
    }
    
    /**
     * 监听session创建及销毁事件,来及时清理session的记录,以确保最新的session状态可以被及时感知到。
     */  
    @Bean
    **public** HttpSessionEventPublisher **httpSessionEventPublisher**() {
        
        **return** **new** HttpSessionEventPublisher();
    }

    @Bean
    **public** PasswordEncoder **passwordEncoder**() {

        **return** NoOpPasswordEncoder.getInstance();
    }

}

也就是说我们只需要添加 **maxSessions PreventsLogin(true)**配置即可,此时一个浏览器登录成功后,另外一个浏览器就登录不了了,效果如下:

图片

另外我们在上面的源码中,还配置了HttpSessionEventPublisher对象的创建。

注意:我们之所以要创建HttpSessionEventPublisher这个Bean,是因为在 Spring Security 中,它可以通过监听session的创建及销毁事件,来及时的清理session记录。

用户从不同的浏览器登录,都会有对应的session,当用户注销登录之后,session就会失效,但是默认的失效是通过调用 StandardSession#invalidate 方法来实现的。这一失效事件无法被 Spring 容器感知到,进而导致当前用户注销登录之后,Spring Security 没有及时清理会话信息表,以为用户还在线,进而导致用户无法重新登录进来。

为了解决这一问题,我们可以提供一个Http Session Event Publisher,这个类实现了Http Session Listener 接口。在该 Bean 中,可以将 session 创建以及销毁的事件及时感知到,并且调用 Spring 中的事件机制将相关的创建和销毁事件发布出去,进而被 Spring Security 感知到,该类部分源码如下:

**public** **void** **sessionCreated**(HttpSessionEvent event) {
  HttpSessionCreatedEvent e = **new** HttpSessionCreatedEvent(event.getSession());
  Log log = LogFactory.getLog(LOGGER_NAME);

  **if** (log.isDebugEnabled()) {
   log.debug("Publishing event: " + e);
  }

  getContext(event.getSession().getServletContext()).publishEvent(e);
 }

 /**
  * Handles the HttpSessionEvent by publishing a {**@link** HttpSessionDestroyedEvent} to
  * the application appContext.
  *
  * **@param** event The HttpSessionEvent pass in by the container
  */
 **public** **void** **sessionDestroyed**(HttpSessionEvent event) {
  HttpSessionDestroyedEvent e = **new** HttpSessionDestroyedEvent(event.getSession());
  Log log = LogFactory.getLog(LOGGER_NAME);

  **if** (log.isDebugEnabled()) {
   log.debug("Publishing event: " + e);
  }

  getContext(event.getSession().getServletContext()).publishEvent(e);
 }

这样我们就实现了会话的并发控制,代码也很简单。

二. 会话并发控制源码解析

两种会话并发控制方案我都已经带着各位实现了,那么底层的实现原理是什么样的呢? 我们一起来看看会话并发控制的源码吧。

UsernamePasswordAuthenticationFilter-->AbstractAuthenticationProcessingFilter-->AbstractAuthenticationProcessingFilter#doFilter()
  1. 会话并发控制执行流程

在Spring Security中,对会话的并发控制也有特定的执行控制流程,该流程是在如下类中被触发执行的:

还有兄弟不知道网络安全面试可以提前刷题吗?费时一周整理的160+网络安全面试题,金九银十,做网络安全面试里的显眼包!

王岚嵚工程师面试题(附答案),只能帮兄弟们到这儿了!如果你能答对70%,找一个安全工作,问题不大。

对于有1-3年工作经验,想要跳槽的朋友来说,也是很好的温习资料!

【完整版领取方式在文末!!】

93道网络安全面试题

内容实在太多,不一一截图了

黑客学习资源推荐

最后给大家分享一份全套的网络安全学习资料,给那些想学习 网络安全的小伙伴们一点帮助!

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

😝朋友们如果有需要的话,可以联系领取~

1️⃣零基础入门
① 学习路线

对于从来没有接触过网络安全的同学,我们帮你准备了详细的学习成长路线图。可以说是最科学最系统的学习路线,大家跟着这个大的方向学习准没问题。

image

② 路线对应学习视频

同时每个成长路线对应的板块都有配套的视频提供:

image-20231025112050764

2️⃣视频配套工具&国内外网安书籍、文档
① 工具

② 视频

image1

③ 书籍

image2

资源较为敏感,未展示全面,需要的最下面获取

在这里插入图片描述在这里插入图片描述

② 简历模板

在这里插入图片描述

因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
img

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

csdnimg.cn/504b8be96bfa4dfb8befc2af49aabfa2.png#pic_center)

因篇幅有限,资料较为敏感仅展示部分资料,添加上方即可获取👆

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以添加V获取:vip204888 (备注网络安全)
[外链图片转存中…(img-MdJlGCyy-1713622001638)]

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值