spring security 会话管理

news2024/12/23 4:50:04

一、简介

    当浏览器调用登录接口登录成功后,服务端会和浏览器之间建立一个会话(Session)浏览器在每次发送请求时都会携带一个 Sessionld,服务端则根据这个 Sessionld 来判断用户身份当浏览器关闭后,服务端的 Session 并不会自动销毁,需要开发者手动在服务端调用Session销毁方法,或者等 Session 过期时间到了自动销毁。在Spring Security 中,与HttpSession相关的功能由 SessionManagemenFiter 和Session AutheaticationStrateey 接口来处理,SessionManagomentFilter 过滤器将Session 相关操作委托给SessionAuthenticationStrategy 接口去完成。

二、会话并发管理

   会话并发管理就是指在当前系统中,同一个用户可以同时创建多少个会话,如果一合设备对应一个会话,那么也可以简单理解为同一个用户可以同时在多少台设备上进行登录。默认情况下,同一用户在多少台设备上登录并没有限制,不过开发者可以在 Spring Security 中对此进行配置。

2.1 开启会话管理

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {



    /**
     * 自定义数据源,从内存中,后期自己写一个mybatis 从数据库查询
     * @throws Exception{scrypt}
     */
    @Bean
    public UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager userDetailsManager = new InMemoryUserDetailsManager();
        userDetailsManager.createUser(User.withUsername("admin").password("{noop}12345").authorities("admin").build());
        return userDetailsManager;
    }

    /**
     *  自定义authenticationManager 管理器,将自定义的数据源加到其中
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService());
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()// 表单登录
                .loginProcessingUrl("/doLogin")
                .and()
                .csrf().disable()
                .sessionManagement()// 开启会管理
                .maximumSessions(1); //设置会话并发数为1

    }
    
    @Bean
    public HttpSessionEventPublisher httpSessionEventPublisher() {
        return new HttpSessionEventPublisher();
    }
    
}
  1. sessionManagement)用来开启会话管理、maximumSessions指定会话的并发数为1。
  2. HttpSessionEventPublisher提供一一个Htp SessionEvenePubishor-实例。Spring Security中通过一个 Map 集合来集护当前的 Http Session 记录,进而实现会话的并发管理。当用户登录成功时,就向集合中添加一条Http Session 记录;当会话销毁时,就从集合中移除一条Httpsession 记录。HtpSesionEvenPublisher 实现了 Fttp SessionListener 接口,可以监听到 HtpSession 的创建和销毁事件,并将 Fltp Session 的创建/销毁事件发布出去,这样,当有 HttpSession 销毁时,Spring Security 就可以感知到该事件了。

2.2 测试会话管理

     配置完成后,启动项目。这次测试我们需要两个浏览器,如果使用了 Chrome 浏览器,可以使用 Chrome浏览器中的多用户方式(相当于两个浏览器)先在第一个浏览器中输入 http://localhost:8081,此时会自动跳转到登录页面,完成登录操作,就可以访问到数据了;接下来在第二个浏览器中也输入 http://localhost:8081,也需要登录完成登录操作;当第二个浏览器登录成功后,再回到第一个浏览器,刷新页面。结果出现下当另外一个浏览器登录后,就把前一个会话挤掉线了;

2.3 会话失效处理(传统web)

protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin()// 表单登录
            .loginProcessingUrl("/doLogin")
            .and()
            .csrf().disable()
            .sessionManagement()// 开启会管理
            .maximumSessions(1) //设置会话并发数为1
            .expiredUrl("/login"); // 会话过期跳转页面

}

这次会话失效后,就会跳到登录页面了,就不会出现这个英文提示了;

2.4 会话失效处理(前后端分离实现)

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin()// 表单登录
            .loginProcessingUrl("/doLogin")
            .and()
            .csrf().disable()
            .sessionManagement()// 开启会管理
            .maximumSessions(1) //设置会话并发数为1
            //.expiredUrl("/login"); // 会话过期跳转页面
            .expiredSessionStrategy(ses -> {
                HttpServletResponse response = ses.getResponse();
                Map<String,String> resMap = new HashMap<>();
                resMap.put("code","5001");
                resMap.put("msg","你的账号已经挤下线了,请重新登录!");

                String resStr = new ObjectMapper().writeValueAsString(resMap);
                response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                response.getWriter().println(resStr);
            });

}

2.5 禁止再此登录

    默认的效果是一种被“挤下线”的效果,后面登录的用户会把前面登录的用户“挤下线。还有一种是禁止后来者登录,即一旦当前用户登录成功,后来者无法再次使用相同的用户登录,直到当前用户主动注销登录,配置如下:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .formLogin()// 表单登录
            .loginProcessingUrl("/doLogin")// 退出登录
            .and()
            .logout()
            .and()
            .csrf().disable()
            .sessionManagement()// 开启会管理
            .maximumSessions(1) //设置会话并发数为1
            //.expiredUrl("/login"); // 会话过期跳转页面
            .expiredSessionStrategy(ses -> {
                HttpServletResponse response = ses.getResponse();
                Map<String,String> resMap = new HashMap<>();
                resMap.put("code","5001");
                resMap.put("msg","你的账号已经挤下线了,请重新登录!");

                String resStr = new ObjectMapper().writeValueAsString(resMap);
                response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                response.getWriter().println(resStr);
                response.flushBuffer();
            }).maxSessionsPreventsLogin(true);// 一旦登录  禁止后来其它账号登录

}


三、会话共享

    前面所讲的会话管理都是单机上的会话管理,也就是在单体架构,如果当前是集群环境,前面所讲的会话管理方案就会失效。此时可以利用 spring-session 结合 redis 实现 session 共享。

3.1 引入依赖

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

3.2 代码配置

@Autowired
private RedisTemplate redisTemplate;

  @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()// 表单登录
                .loginProcessingUrl("/doLogin")// 退出登录
                .and()
                .logout()
                .and()
                .csrf().disable()
                .sessionManagement()// 开启会管理
                .maximumSessions(1) //设置会话并发数为1
                //.expiredUrl("/login"); // 会话过期跳转页面
                .expiredSessionStrategy(ses -> {
                    HttpServletResponse response = ses.getResponse();
                    Map<String,String> resMap = new HashMap<>();
                    resMap.put("code","5001");
                    resMap.put("msg","你的账号已经挤下线了,请重新登录!");

                    String resStr = new ObjectMapper().writeValueAsString(resMap);
                    response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
                    response.getWriter().println(resStr);
                    response.flushBuffer();
                })
                //.maxSessionsPreventsLogin(true);// 一旦登录  禁止后来其它账号登录
                .sessionRegistry(sessionRegistry());// 将session 交给谁管理

    }

// 创建session 同步到redis中方案
@Bean
public SpringSessionBackedSessionRegistry sessionRegistry() {
    FindByIndexNameSessionRepository indexNameSessionRepository = new RedisIndexedSessionRepository(redisTemplate);
    return new SpringSessionBackedSessionRegistry(indexNameSessionRepository);
}

最终查看redis结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2092186.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

结构型设计模式-适配器(adapter)模式-python实现

设计模式汇总&#xff1a;查看 通俗示例 想象一下&#xff0c;你刚从国外带回一台最新的笔记本电脑&#xff0c;但是你发现它的电源插头是德标插头&#xff0c;而家里的电源插座是中式插座&#xff0c;这时怎么办呢&#xff1f;你需要一个电源适配器来将德标插头转换成中式插座…

“萌宠经济”全球化浪潮:宠物品牌如何利用TikTok达人破局出海

在全球“萌宠经济”不断升温的背景下&#xff0c;宠物品牌出海成为了重要的战略。随着市场的增长和消费者对宠物产品的需求增加&#xff0c;品牌需要寻找有效的方式进入新的海外市场。在这种情况下&#xff0c;TikTok平台的崛起和宠物达人的影响力成为了宠物品牌破局出海的关键…

数据结构与算法(快速基础C++版)

数据结构与算法&#xff08;快速基础C版&#xff09; 1. 基本概念第1章 绪论1.1 数据结构的研究内容1.2 基本概念和术语1.2.1 数据、数据元素、数据项和数据对象1.2.2 数据结构1.2.3 数据类型和抽象数据类型1.2.4 概念小结 1.3 算法和算法分析1.4 总结 2. 基本的数据结构第2章 …

【PyTorch常用库函数】一文教你快速上手torch.abs()函数:获取张量的绝对值

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 引言 在深度学习领域&#xff0c;PyTorch是一个非常受欢迎的框架&#xff0c;它提供了丰富的库函数来支持各种复杂的计算任务。…

利用Leaflet.js创建交互式地图:多种形状单个区域绘制

引言 在地图应用开发中&#xff0c;用户经常需要对特定区域进行标识和规划。本文将深入探讨如何利用Vue.js的响应式特性与Leaflet.js的地图功能&#xff0c;打造一个支持多边形、矩形、圆形等多种形状绘制的交互式地图编辑器。 功能亮点 自由绘制多边形&#xff1a;用户可以自…

mysql基础语法——个人笔记

0 前言 以前学习且实践过mysql&#xff0c;但后来用得少&#xff0c;随着岁月更替&#xff0c;对其印象渐浅&#xff0c;所以每次需要用时&#xff0c;都会去再看一眼语法规范&#xff0c;然后才能放心动手操作 然而&#xff0c;在信息爆炸的时代&#xff0c;查语法规范时&am…

BUUCTF PWN wp--jarvisoj_level0

第一步 checksec &#xff0c;该题为64位。 分析一下二进制保护机制&#xff1a; Arch: amd64-64-little 这个字段表示二进制程序的架构是 64 位的小端序的 x86-64 架构。小端序意味着低位字节存储在内存中的低地址上&#xff0c;高位字节存储在高地址上。RELRO: No RELRO …

迁移学习之领域自适应(domain adaptation)

比如有一堆有标注的训练数据&#xff0c;这些数 据来自源领域&#xff0c;用这些数据训练出一个模型&#xff0c;这个模型可以用在不一样的领域。在训练的时 候&#xff0c;我们必须要对测试数据所在的目标领域有一些了解。 随着了解的程度不同&#xff0c;领域自适应的方法也不…

(C++ STL)vector类的简单模拟实现与源码展示

vector类的简单模拟实现 一、前言二、vector 的成员变量三、vector 部分函数实现size、capacityreserveresizeinsert 与注意事项erase构造、析构、赋值拷贝 四、vector 源代码 以下代码环境为 VS2022 C。 一、前言 vector类 本质上就是数据结构中的顺序表。(可参考&#xff1…

【最新华为OD机试E卷】boos的收入(100分)-多语言题解-(Python/C/JavaScript/Java/Cpp)

🍭 大家好这里是春秋招笔试突围 ,一枚热爱算法的程序员 ✨ 本系列打算持续跟新华为OD-E/D卷的三语言AC题解 💻 ACM金牌🏅️团队| 多次AK大厂笔试 | 编程一对一辅导 👏 感谢大家的订阅➕ 和 喜欢💗 🍿 最新华为OD机试D卷目录,全、新、准,题目覆盖率达 95% 以上,…

4.负载均衡

文章目录 1.多级部署2.实现请求计数器3.负载均衡3.1服务端负载均衡3.2客户端负载均衡3.3自定义负载均衡3.4负载均衡策略3.5 LoadBalance 原理 4.部署实现 大家好&#xff0c;我是晓星航。今天为大家带来的是 负载均衡 相关的讲解&#xff01;&#x1f600; 1.多级部署 复制一…

C语言 | Leetcode C语言题解之第378题有序矩阵中第K小的元素

题目&#xff1a; 题解&#xff1a; bool check(int **matrix, int mid, int k, int n) {int i n - 1;int j 0;int num 0;while (i > 0 && j < n) {if (matrix[i][j] < mid) {num i 1;j;} else {i--;}}return num > k; }int kthSmallest(int **matri…

面试题小总结

一、为什么要使用Redis&#xff1f; 因为它是内存数据库&#xff0c;运行速度快因为它的工作线程是单线程&#xff0c;具有串行化&#xff0c;原子性具有IO模型&#xff0c;天生支撑高并发是kv模型&#xff0c;v具有多个数据结构具有本地方法&#xff0c;可以计算数据移动是二…

Mac用户必备:轻松添加Git SSH密钥全攻略

最近新买了一台MacBook笔记本&#xff0c;然后安装了git&#xff0c;准备下载代码&#xff0c;正好遇到配置GitHub的ssh密钥&#xff0c;记录一下整个操作流程。 操作步骤 在Mac上添加Git SSH密钥的步骤如下&#xff1a; 检查是否已有SSH密钥&#xff1a; 打开终端&#xff0…

Nginx: https解决安全问题

https原理 1 &#xff09;http协议存在的问题 数据使用明文传输&#xff0c;可能被黑客窃取 (需要信息加密)报文的完整性无法验证&#xff0c;可能被黑客篡改 (需要完整性校验)无法验证通信双方的身份&#xff0c;可能被黑客伪装 (需要身份认证) 2 ) https 原理 所谓 https,…

新160个crackme - 043-riijj_cm_20041121

运行分析 除了主程序还有一个dll文件&#xff0c;应该是要加载pf1.dll这个动态链接库运行主程序&#xff0c;需破解Name和Serial&#xff0c;点击注册无反应 PE分析 C程序&#xff0c;32位&#xff0c;无壳 静态分析&动态调试 尝试ida动调加载动态链接库pf1.dll&#xff0c…

全能型AI“草莓”:未来趋势还是市场泡沫?

你好&#xff0c;我是三桥君 近日&#xff0c;OpenAI宣布将在秋季推出代号为“草莓”的新AI模型。这一消息迅速引起了科技界和市场的广泛关注。 OpenAI的新项目“草莓”&#xff08;Strawberry&#xff09;是一个备受关注的人工智能模型&#xff0c;预计将在今年秋季发布。这个…

算法复盘——LeetCode hot100:哈希

文章目录 哈希表哈希表的基本概念哈希表的使用1. 插入操作2. 查找操作3. 删除操作 哈希表的优点和缺点1.两数之和复盘 242.有效的字母异位词复盘 49.字母异位词分组复盘 128. 最长连续序列复盘HashSet 哈希表 先来搞清楚什么是哈希表吧~ 概念不清楚方法不清楚怎么做题捏 哈希表…

MongonDB-索引

一、索引-index (一) 概述 索引支持在MongoDB中高效地执行查询。如果没有索引&#xff0c;MongoDB必须执行全集合扫描&#xff0c;即扫描集合中的每个文档&#xff0c;以选择与查询语句匹配的文档。这种扫描全集合的查询效率是非常低的&#xff0c;特别在处理大量的数据时&am…

firewalld 防火墙常用命令,新手必看

firewalld 防火墙常用命令 防火墙状态命令 systemctl start firewalld #启动防火墙 systemctl stop firewalld #关闭防火墙 systemctl restart firewalld #重启防火墙 systemctl enable firewalld #设置开机自启 systemctl disable firewalld #禁用开机自启 systemctl s…