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

6 篇文章 0 订阅
4 篇文章 0 订阅

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.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.0.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <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>
    </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并发就是测不出来。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值