• security 会话并发管理


    一、简介

    会话指得是浏览器和服务端通过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 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共享

    引入依赖

            
                org.springframework.boot
                spring-boot-starter-data-redis
            
            
                org.springframework.session
                spring-session-data-redis
            

    系统配置文件配置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);
        }
    }
  • 相关阅读:
    Linux系统编程(一)——环境搭建
    重读经典:《The Craft of Research(1)》
    使用Docker部署Python Flask应用的完整教程
    数学建模竞赛最全竞赛案例分析总结
    elasticsearch wildcard 慢查询原因分析(深入到源码!!!)
    3D激光线扫相机与结构光相机的区别
    基于JAVA快递物流管理计算机毕业设计源码+系统+mysql数据库+lw文档+部署
    Linux系统yum安装拓展
    搜狗收录量易语言查询代码
    红蓝对抗-攻防演练中红队如何识别蜜罐保护自己
  • 原文地址:https://blog.csdn.net/qq_34491508/article/details/126102477