security 会话并发管理

本文详细介绍了如何使用Spring Security进行会话并发管理,包括默认配置下允许同一用户在多台设备登录,以及如何配置限制同一账号只能在一个浏览器登录。当会话超时时,展示了如何自定义提示信息,并提供了传统Web开发和前后端分离场景下的处理方式。此外,还讲解了如何禁止再次登录以及在分布式环境中利用Spring Session和Redis实现会话共享。
摘要由CSDN通过智能技术生成

一、简介

会话指得是浏览器和服务端通过session交互过程

二、会话并发管理

1、什么是会话并发

当前系统中,同一个用户是否可以在多台设备登录,springsecurity默认没有限制,可以在多台设备登录,可以在springsecurity中配置管理

2、代码

引入security不做任何配置 默认同一个账号是可以在多个浏览器登录访问系统

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf().disable()
                .sessionManagement()//开启会话管理
                .maximumSessions(1);//同一个账号只能在一个浏览器登录
    }

    /**
     *找个bean可以不加,但是建议加上
     * security提供一个map来集护当前http session记录 实现会话并发管理,当登录时候增加一条 ,退出时从集合移除一个
     */
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher(){
        return new HttpSessionEventPublisher();
    }
}

当多个浏览器登录时候出现如下提示

This session has been expired (possibly due to multiple concurrent logins being attempted as the same user).

会话失效我们该如何改变找个提示?

3、会话被挤下线时处理

3.1、传统web开发

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf().disable()
                .sessionManagement()
                .maximumSessions(1)
                .expiredUrl("/login");//被挤下线时候跳转地址
    }
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher(){
        return new HttpSessionEventPublisher();
    }
}

3.2、前后端分离

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf().disable()
                .sessionManagement()
                .maximumSessions(1)
                .expiredSessionStrategy(event -> {
                    HttpServletResponse response = event.getResponse();
                    Map<String,Object> map = new HashMap<>();
                    map.put("code",500);
                    map.put("msg","当前账号异地登录");
                    String result = new ObjectMapper().writeValueAsString(map);
                    response.setContentType("application/json;charset=UTF-8");
                    response.getWriter().println(result);
                    response.flushBuffer();
                });//参数是个函数式接口 直接用lambda处理
    }
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher(){
        return new HttpSessionEventPublisher();
    }
}

4、禁止再次登录

默认是被挤下线方式 可以设置后来者无法登录

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf().disable()
                .sessionManagement()
                .maximumSessions(1)
                .expiredUrl("/login")
                .maxSessionsPreventsLogin(true);//一旦登录 禁止再次登录
    }
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher(){
        return new HttpSessionEventPublisher();
    }
}

5、分布式会话共享

上面会话都是通过内存中的map集中管理,所以无法在分布式集群系统中共享,要在集群中使用,就要用spring-session集合redis实现session共享

引入依赖

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

系统配置文件配置redis

spring.redis.port=6379
spring.redis.url=localhost

security配置

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    //注入session管理方案
    @Autowired
    private FindByIndexNameSessionRepository findByIndexNameSessionRepository;
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .and()
                .csrf().disable()
                .sessionManagement()
                .maximumSessions(1)
                .expiredUrl("/login")
                .sessionRegistry(sessionRegistry())//将session交给谁管理
                .maxSessionsPreventsLogin(true);
    }

    /**
     * 创建session 同步到redis的方案
     */
    @Bean
    public SpringSessionBackedSessionRegistry sessionRegistry(){
        return new SpringSessionBackedSessionRegistry(findByIndexNameSessionRepository);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序三两行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值