《SpringSecurity in Action》三:Session并发控制问题

《SpringSecurity in Action》三:Session并发控制问题,第1张

文章目录
    • 1 概述
    • 2 实现方法
    • 3 测试方法

1 概述

Session并发控制指服务端控制客户端某个用户同时在线的数量,如某个账号在谷歌浏览器上进行了登陆,又在IE浏览器上进行了登陆,又在手动app上进行了登陆,那这时session并发数就是3.控制session并发的意思一是在于控制服务器资料占用,二是可以起到对帐号的保护作用。比较我们是不是都有这样的经历,我们正登着QQ呢,突然自己登出了,不久QQ就给我们发了一条消息,说你的帐号在哪哪哪登陆了,如果不是本人 *** 作赶快修改密码。这就是session并发控制。如果没有session并发控制,那么你的帐号被他人登陆后,那么你将毫无感知。

2 实现方法

使用SpringSession实现Session并发很简单,如果你的要求不高,只需要一行代码就可以了,在protected void configure(HttpSecurity http)这个方法里加上.maximumSessions(2)就OKAY, 这行配置的参数表示服务端最多允许几个客户端帐号同时在线。

完整的代码示例:
主要依赖

    <parent>
        <groupId>org.springframework.bootgroupId>
        <artifactId>spring-boot-starter-parentartifactId>
        <version>2.3.0.RELEASEversion>
        <relativePath/> 
    parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-securityartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.bootgroupId>
            <artifactId>spring-boot-starter-data-redisartifactId>
        dependency>
        <dependency>
            <groupId>org.springframework.sessiongroupId>
            <artifactId>spring-session-data-redisartifactId>
        dependency>
    dependencies>

配置文件

spring:
  redis:
    host: 256.73.82.27 # 地址,这个ip是瞎写的,第一位是256就不可能的对吧
    port: 6379 # 端口
    database: 1 # 数据库索引
    password: redis

  session:
    store-type: redis

SpringSecurity配置类

/**
     * 这个Bean的作业是在登出时,进行一个发布,具体做了什么还不是很清楚
     * 如果没有该Bean,现象是如果配置了http.maxSessionsPreventsLogin(true),当用户登陆数量后,即使进行登出 *** 作,接下来也还是不能正常登陆。
     */
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }

@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            /*
             * 省力其它配置信息
             */
            .sessionManagement()
            // 最大session并发数
            .maximumSessions(2)
            /*
             * 省力其它配置信息
             */
3 测试方法

启动服务

  • 登陆请求A: 使用curl发起登陆请求curl -X POST -v -H 'Content-Type: application/x-www-form-urlencoded' -d 'username=testUser' -d 'password=123' 'localhost:8765/hgd11-security-api/login'
    请求出参:

  • 登陆请求B: 再次使用curl发起登陆请求curl -X POST -v -H 'Content-Type: application/x-www-form-urlencoded' -d 'username=testUser' -d 'password=123' 'localhost:8765/hgd11-security-api/login'

  • 登陆请求C: 再次使用curl发起登陆请求curl -X POST -v -H 'Content-Type: application/x-www-form-urlencoded' -d 'username=testUser' -d 'password=123' 'localhost:8765/hgd11-security-api/login'

  • 业务请求D: 使用登陆请求A时响应的session,请求业务接口curl -X GET -v 'localhost:8765/hgd11-security-api/test/hello' -H 'Cookie: SESSION=NGJjZjdmYzktYzZiMS00Mjg2LTg4MGMtNDBkMmFmNDFkZTNk',发现请求认证失败。

测试过程值得说的几点

  1. 一定要连接进行后两次请求后,也就是测试顺序的A-B-C后,再使用第一次登陆获取的session做业务请求D,这时才能测试出来session并发的效果来。因为在发生session并发时,SpringSecurity是根据session里最后更新时间来判断驱逐哪个session的。最早的那个更新时间对应的session会被驱逐。如果测试顺序是A-B-D-C-D,这时你期望的是A那次登陆会被驱逐,但实际上A并不会被驱逐,而是请求登陆B那次被驱逐了,因为进行D *** 作后,D session的最后更新时间比B的session要更新。
  2. 之所以使用curl进行测试,而没有使用postman,是因为postman在请求时会自动带上cookie,也就是说会把sessionID带过去。更详细的情况是这样的,进行登陆请求A时,服务器响应了一个sessionID,这时postman把session放在cookie里;进行登陆请求B时,这次登陆请求全带着sessionID过去,服务器看到有sessionID,就知道是同一个客户端,这时只是会change一下sessionId,不会再创建session了,所以session也就不存在并发了。
  3. 先不要在多副本的情况下测试

如果不知情,使用postman一直来测试session并发,可能测到死也不明白为什么session并发就是测不出来。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/787651.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-05
下一篇 2022-05-05

发表评论

登录后才能评论

评论列表(0条)

保存