Spring Security 6.x 系列(13)—— 会话管理及源码分析(一)

news2024/12/30 3:56:28

一、会话概念

在实现会话管理之前,我们还是先来了解一下协议和会话的概念,连协议和会话都不知道是啥,还谈啥管理。

1.1 http 协议

因为我们现在的会话,基本上都是基于HTTP协议的,所以在讲解会话之前,我再带各位复习一下HTTP协议。

1.1.1 概念

HTTP:超文本传输协议(HyperText Transfer Protocol),是一种用于分布式、协作式和超媒体信息系统的应用层协议,是一种在客户端(用户)和服务器端(网站)之间进行请求和响应的规范标准(TCP),HTTP是万维网中数据通信的基础。

1.1.2 起源&发展

HTTP的发展是由蒂姆·伯纳斯-李于1989年在欧洲核子研究组织(CERN)所发起。HTTP的标准制定由万维网协会(World Wide Web Consortium,W3C)和互联网工程任务组(Internet Engineering Task Force,IETF)进行协调,最终发布了一系列的RFC。其中最著名的是1999年6月公布的 RFC 2616,定义了HTTP协议中现今广泛使用的一个版本—— HTTP 1.1

2014年12月,互联网工程任务组(IETF)的Hypertext Transfer Protocol Bishttpbis)工作小组将HTTP/2标准提议递交至IESG进行讨论,于2015年2月17日被批准。HTTP/2标准于2015年5月以RFC 7540正式发表,取代HTTP 1.1成为HTTP的实现标准

1.1.3 特点

  • 基于 请求-响应 模式:

    HTTP协议规定:请求是从客户端发出的,最后由服务器端接受并响应该请求。

  • 无状态保存:

    HTTP是一种不保存用户状态,即无状态(stateless)的协议。HTTP协议自身不对请求和响应之间的通信状态进行保存,也就是说在HTTP这个级别,协议对于发送过的请求或响应都不做持久化处理。

    HTTP协议的无状态,指的是每当有新的请求发送时,就会有对应的响应产生,HTTP协议本身并不保留之前一切的请求或响应的报文信息。这是为了更快地处理大量事务,确保协议的可伸缩性,而特意把HTTP协议设计成如此简单的。可随着Web的不断发展,因无状态而导致业务处理变得棘手的情况也增多了。比如:用户登录到一家购物网站,然后他跳转到该站的其他页面,也需要能继续保持登录状态。针对这个实例,网站为了能够掌握是谁发送的请求,需要保存用户的状态。HTTP/1.1虽然是无状态的协议,但为了实现期望的保持状态的功能,于是就引入了CookieSession技术。有了CookieSession,再用HTTP协议通信,就可以管理状态了。

  • 无连接:

    无连接的含义就是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间,并可以提高并发性能,不用和每个用户建立长久的连接,请求一次响应一次,服务端和客户端就中断了。

1.2 会话概念

会话(Session):在计算机中,尤其是在网络应用中,称为会话控制,它是以无状态的HTTP协议来维持用户状态的一种解决方案。

我们知道HTTP是无状态的协议,这意味着每次客户端检索网页时,都要单独打开一个服务器连接,因此服务器不会存储先前客户端请求的任何信息。

HTTP 本身的无状态使得用户在与服务器的交互过程中,每个请求之间都没有关联性。这意味着用户的访问没有身份记录,站点也无法为用户提供个性化的服务,而Session的诞生解决了这个难题。服务器通过与用户约定,发起每个请求时都要携带一个id类的信息,从而让不同请求之间有了关联,而id又可以很方便地绑定具体用户,所以我们可以把不同请求归类到同一用户。基于这个方案,为了让用户每个请求都携带同一个id,在不妨碍体验的情况下,cookie是很好的载体。当用户首次访问系统时,系统会为该用户生成一个sessionid,并添加到cookie中。在该用户的会话期内,每个请求都自动携带该cookie,因此系统可以很轻易地识别出这是来自哪个用户的请求。

jsessionid就是客户端用来保存sessionid的变量,主要是针对j2ee实现的web容器。

尽管 cookie 非常有用,但有时用户会在浏览器中禁用它,这么做可能是出于安全考虑,也可能是为了保护个人隐私。

在这种情况下,基于cookie实现的 sessionld 自然就无法正常使用了。因此,有些服务还支持用 URL重写 的方式来实现类似的体验,例如:http://www.baidu.com;jessionid=xxx URL重写原本是为了兼容禁用 cookie 的浏览器而设计的,但也容易被黑客利用。黑客只需访问一次系统,将系统生成的sessionld提取并拼凑在URL上,然后将该URL发给一些取得信任的用户。只要用户在session有效期内通过此URL进行登录,该sessionld就会绑定到用户的身份,黑客便可以轻松享有同样的会话状态,完全不需要用户名和密码,这就是典型的会话固定攻击。

我们只需在两个浏览器中用同一个账号登录就会发现,默认情况下,我们的系统并未有任何会话并发的限制,也就是一个账户能在多处同时登录,这并不是一个好的策略。而Spring Security已经为我们提供了完善的会话管理功能,包括:会话固定攻击会话超时检测以及会话并发控制等。

1.3 HttpSession

HttpSession 是一个服务端的概念,服务端生成的 HttpSession 都会有一个对应的 sessionid,这个 sessionid 会通过 cookie 传递给前端,前端以后每次发送请求的时候,都会带上这个 sessionid 参数。服务端看到这个 sessionid 就会把这个前端请求和服务端的某一个 HttpSession 对象对应起来,形成会话的感觉。

浏览器关闭并不会导致服务端的 HttpSession 失效,想让服务端的 HttpSession 失效,要么手动调用 HttpSession#invalidate()方法,要么等到 session 自动过期,要么重启服务端。

但是为什么有的人会感觉浏览器关闭之后 session 就失效了呢?这是因为浏览器关闭之后,保存在浏览器里边的 sessionid 就丢了(默认情况下)。所以当浏览器再次访问服务端的时候,服务端会给浏览器重新分配一个 sessionid,这个 sessionid 和之前的 HttpSession 对应不上,所以用户就会感觉 session 失效。

但是我们也可以通过手动配置,让浏览器重启之后 sessionid 不丢失,但是这样会带来安全隐患,所以一般不建议。

Spring Boot 为例,服务端生成 sessionid 之后,返回给前端的响应头是这样的:

在这里插入图片描述

在服务端的响应头中有一个 Set-Cookie 字段,该字段指示浏览器更新 sessionid,同时大家注意还有一个 HttpOnly 属性,这个表示通过 JS 脚本无法读取到 Cookie 信息,这样能有效的防止 XSS 攻击。

下一次在浏览器中发送对某个接口的请求时候,就会自觉的携带上这个 sessionid 了:

在这里插入图片描述

二、会话配置

2.1 创建策略

Spring Security 中的 SessionCreationPolicy 枚举类,声明了会话的创建策略:

public enum SessionCreationPolicy {

	/**
	 * Always create an {@link HttpSession}
	 */
	ALWAYS,

	/**
	 * Spring Security will never create an {@link HttpSession}, but will use the
	 * {@link HttpSession} if it already exists
	 */
	NEVER,

	/**
	 * Spring Security will only create an {@link HttpSession} if required
	 */
	IF_REQUIRED,

	/**
	 * Spring Security will never create an {@link HttpSession} and it will never use it
	 * to obtain the {@link SecurityContext}
	 */
	STATELESS

}

通过以下选项准确控制会话合适创建及 Spring Security 合适与之交互:

策略名称描述
ALWAYS如果没有存 Session 就创建一个
NEVER不会创建 Session ,但是如果应用中其他地方创了,那么 Spring Security 将会使用它
IF_REQUIRED如果需要就创建一个 Session(默认)
STATELESS绝对不会创建 Session ,也不使用 Session ,每个请求都需要重新进行身份验证

通过以下方式对改策略进行配置:

// 会话创建策略
http.sessionManagement(session -> session
        .sessionCreationPolicy(SessionCreationPolicy.ALWAYS)
        );

默认情况下, Spring Security 会为每个登录成功的用户创建一个 Session 也就是使用 IF_REQUIRED 策略。

2.2 检测超时

2.2.1 超时时间

可以在 Sevlet 容器中设置 Session 的有效期,如下设置有效期为3600秒(默认):

server:
  servlet:
    session:
      timeout: 3600s

2.2.2 失效跳转路径

会话超时之后,可以通过Spring Security 设置失效跳转路径:

http.sessionManagement(session -> session
                .invalidSessionUrl("/login?error=INVALID_SESSION") //  失效跳转路径
                .sessionCreationPolicy(SessionCreationPolicy.ALWAYS) // 创建策略
        );

如果用户注销没有关闭浏览器,浏览器中的 cookie 不会被清除,注销登录时可以明确地删除名称为JSESSIONIDcookie

http.logout(logout -> logout
        .deleteCookies("JSESSIONID")
    );

注意:
这不能保证适用于每个 servlet 容器,因此您需要在您的环境中对其进行测试。

下面的方法与容器无关,并且适用于任何支持标头的容器:

HeaderWriterLogoutHandler clearSiteData = new HeaderWriterLogoutHandler(new ClearSiteDataHeaderWriter(ClearSiteDataHeaderWriter.Directive.ALL));
http.logout(logout -> logout.addLogoutHandler(clearSiteData));

2.3 无效会话策略

通过定义 CustomInvalidSessionStrategy 实现 InvalidSessionStrategy 接口,配置无效会话策略:

http
    .sessionManagement(session -> session
        .invalidSessionStrategy(new CustomInvalidSessionStrategy())
    );

2.4 会话失效策略

在前后端分离时,会话失效不会虚后端跳转页面,可以设置返回JSON数据:

.sessionConcurrency(sessionConcurrency -> sessionConcurrency.expiredSessionStrategy(event -> {
            HttpServletResponse response = event.getResponse();
            response.setContentType("application/json;charset=utf-8"); // 返回JSON
            response.setStatus(HttpStatus.BAD_REQUEST.value());  // 状态码
            Map<String, Object> result = new HashMap<>(); // 返回结果
            result.put("msg", "当前会话已失效");
            result.put("code", 401);
            response.getWriter().write(JSONUtil.toJsonStr(result));
        })
)

注意:expiredSessionStrategyConcurrencyControlConfigurer中的方法。

2.5 并发控制

并发控制可以限制在当前系统中,同一个用户可以同时创建的会话数量。一般用于踢人下线,当同一用户登录后,在另一个地方重新登录,会让之前登录的用户直接退出,提示您的账号已经在其他地方登录。默认配置是没有限制的。

首先添加一个监听器,监听会话声明周期事件:

@Bean
public HttpSessionEventPublisher httpSessionEventPublisher() {
    return new HttpSessionEventPublisher();
}

配置 maximumSessions 限制用户最大会话数为 1第二次登录会导致第一次登录失效

配置 maxSessionsPreventsLogin 如果为 true ,已登录时,阻止其他登录。

// 会话策略
 http.sessionManagement(session -> session
                 .maximumSessions(1)  // 用户最大会话数为 1,后面的登陆就会自动踢掉前面的登陆
                 .maxSessionsPreventsLogin(true); // 已登录时,阻止其他登录
         );

在一个浏览器登录成功后切换到另一个浏览器再次登录时,提示最大会话数超出限制:

在这里插入图片描述

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

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

相关文章

openmediavault(OMV) (26)网络(1)ddns-go

简介 "ddns-go" 是一个动态域名解析(Dynamic DNS)工具,用于更新域名的IP地址。它可以自动检测你的公共IP地址,并将其更新到指定的域名解析服务商,以确保你的域名始终与最新的IP地址相匹配。 安装 hub.docker.com上下载ddns-go镜像 配置compose文件 --- versio…

使用 Process Explorer 和 Windbg 排查软件线程堵塞案例分享

目录 1、问题说明 2、线程堵塞的可能原因分析 3、使用Windbg和Process Explorer确定线程中发生了死循环 4、根据Windbg中显示的函数调用堆栈去查看源码&#xff0c;找到问题 4.1、在Windbg定位发生死循环的函数的方法 4.2、在Windbg中查看变量的值去辅助分析 4.3、是循环…

ModStartCMS v7.9.0 内容推荐支持,用户授权升级

ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用&#xff0c;支持后台一键快速安装&#xff0c;让开发者能快的实现业务功能开发。 系统完全开源&#xff0c;基于 Apache 2.0 开源协议&#xff0c;免费且不限制商业使用。 功能特性 丰富的模块市…

CMake入门教程【基础篇】HelloCMake

文章目录 概述核心实现代码示例使用技巧注意事项 总结 概述 CMake是一个强大的跨平台构建系统&#xff0c;广泛用于C和C项目。它使用简单的配置文件来生成标准的构建文件&#xff0c;从而使得构建过程跨平台且易于管理。本教程将通过一个“Hello World”示例&#xff08;命名为…

必看 | 如何用「八爪鱼RPA」搬迁旧帮助中心站点到「HelpLook」?

对于工具类产品而言&#xff0c;帮助中心的搭建是非常重要的&#xff1a;一个好用的帮助中心&#xff0c;不仅可以帮助用户快速找到所需内容&#xff0c;提升用户的满意度&#xff1b;还可以减轻客服人员的压力&#xff0c;为公司节约大量的人力资源。 以八爪鱼采集器的帮助中心…

【Leetcode】466. 统计重复个数

文章目录 题目思路代码 题目 466. 统计重复个数 思路 题目要求找出一个最大整数 m&#xff0c;使得经过 n2 个字符串 s2 组成的字符串能够被经过 n1 个字符串 s1 组成的字符串完全包含的次数。使用动态规划来记录每个位置匹配的情况&#xff0c;并通过循环节的分析来计算最…

安全数据交换系统:有效提升网间文件交换能力

各级政府部门和金融、能源、电力这些行业&#xff0c;以及一些大中型企业组织&#xff0c;为了保护内部的重要数据不外泄&#xff0c;普遍都采用了多网络并行的方式&#xff0c;也是做了网络隔离划分&#xff0c;不同的网络拥有不同的密级以及人员权限。然后再通过安全数据交换…

C++Qt6 哈夫曼编码求解 数据结构课程设计 | JorbanS

一、 问题描述 在进行程序设计时&#xff0c;通常给每一个字符标记一个单独的代码来表示一组字符&#xff0c;即编码。在进行二进制编码时&#xff0c;假设所有的代码都等长&#xff0c;那么表示 n 个不同的字符需要 位&#xff0c;称为等长编码。如果每个字符的使用频率相等&…

系列七、Ribbon

一、Ribbon 1.1、概述 Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的工具&#xff0c;是Netflix发布的一款开源项目&#xff0c;其主要功能是提供客户端的软件负载均衡算法和服务调用&#xff0c;Ribbon客户端组件提供一系列完善的配置项&#xff0c;例如&#xff1a…

免费证书Let’s Encrypt

免费SSL证书是一种用于保护网站数据传输安全的加密技术。它能够确保用户与网站之间的信息传输是加密的&#xff0c;防止被黑客窃取或篡改。随着网络安全意识的提高&#xff0c;越来越多的网站开始使用SSL证书来保护用户的隐私和数据安全。 在过去&#xff0c;SSL证书需要购买才…

OpenAI官方发布ChatGPT 提示词指南,六大策略让你玩转大语言模型!

OpenAI前段时间官方放出了自己的提示工程指南&#xff0c;从大模型小白到开发者&#xff0c;都可以从中消化出不少营养。看看全世界最懂大模型的人&#xff0c;是怎么写提示词的。官方给出了6 个大提示策略&#xff1a; 1、清晰的指令&#xff1a; 告诉AI你具体想要什么。比如…

ElasticSearch的DSL查询语法解析

Elasticsearch提供了基于ISON的DSL (Domain Specific Lanquage)来定义查询。 目录 一、常见查询类型 二、DSLQuery基本语法 三、全文检索查询 3.1 match查询&#xff1a;会对用户输入内容分词&#xff0c;常用于搜索框搜索 &#xff0c;语法&#xff1a; 3.2 multi match…

RK3568 学习笔记 : 解决 linux_sdk 编译 python 版本报错问题

前言 最近买了 【正点原子】 的 RK3568 开发板&#xff0c;下载了 开发板的资料&#xff0c;包括 Linux SDK&#xff0c;这个 Linux SDK 占用的空间比较大&#xff0c;扩展了一下 VM 虚拟机 ubuntu 20.04 的硬盘空间&#xff0c;编译才正常通过。 编译 RK3568 Linux SDK 时&am…

STM32存储左右互搏 SPI总线读写FRAM MB85RS2M

STM32存储左右互搏 SPI总线读写FRAM MB85RS2M 在中低容量存储领域&#xff0c;除了FLASH的使用&#xff0c;&#xff0c;还有铁电存储器FRAM的使用&#xff0c;相对于FLASH&#xff0c;FRAM写操作时不需要预擦除&#xff0c;所以执行写操作时可以达到更高的速度&#xff0c;其…

Postgresql源码(119)PL/pgSQL中ExprContext的生命周期

前言 在PL/pgSQL语言中&#xff0c;执行任何SQL都需要通过SPI调用SQL层解析执行&#xff0c;例如在SQL层执行表达式的入口&#xff1a; static bool exec_eval_simple_expr(PLpgSQL_execstate *estate,PLpgSQL_expr *expr,Datum *result,bool *isNull,Oid *rettype,int32 *re…

RK3568驱动指南|第九篇 设备模型-第95章 创建属性文件并实现读写功能实验1

瑞芯微RK3568芯片是一款定位中高端的通用型SOC&#xff0c;采用22nm制程工艺&#xff0c;搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码&#xff0c;支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU&#xff0c;可用于轻量级人工…

《PySpark大数据分析实战》-23.Pandas介绍DataFrame介绍

&#x1f4cb; 博主简介 &#x1f496; 作者简介&#xff1a;大家好&#xff0c;我是wux_labs。&#x1f61c; 热衷于各种主流技术&#xff0c;热爱数据科学、机器学习、云计算、人工智能。 通过了TiDB数据库专员&#xff08;PCTA&#xff09;、TiDB数据库专家&#xff08;PCTP…

STM32H5XX和STM32H7XX选型对比

文章目录 STM32H563/H573STM32H743/753对比内核不同H5独有安全管理器H7的外设资源更丰富 STM32H563/H573 STM32H563和STM32H573微控制器扩展了STM32高性能产品组合。这两款微控制器具有增强的性能和安全性、更高的能效和更多的片内外设。 STM32H563/573产品系列提供1至2 MB的…

ChatGPT 4.0真的值得花钱买入吗?

性能提升&#xff1a; ChatGPT 4.0的推出不仅意味着更先进的技术&#xff0c;还代表着更强大的性能。相较于3.5&#xff0c;4.0在处理任务时更为高效&#xff0c;响应更迅速。 更智能的理解&#xff1a; 随着版本的升级&#xff0c;ChatGPT 4.0对语境的理解能力得到了进一步的…

Unity游戏资源更新(AB包)

目录 前言&#xff1a; 一、什么是AssetBundle 二、AssetBudle的基本使用 1.AssetBundle打包 2.BuildAssetBundle BuildAssetBundleOptions BuildTarget 示例 3.AssetBundle的加载 LoadFromFile LoadFromMemory LoadFromMemoryAsync UnityWebRequestAsssetBundle 前…