有/无状态会话 与 Session 与 Spring Security

news/2024/12/19 4:20:39/

一、会话(Session)的基本概念

会话是服务器与客户端之间持续交互的机制。在 Web 应用中,每当用户通过浏览器访问应用时,服务器通常会为其创建一个唯一的会话标识(Session ID),并通过 Cookie(通常是 JSESSIONID)将该标识返回给客户端。客户端在后续的每次请求中都会携带这个 Session ID,从而使服务器能够识别出该请求属于哪个用户的会话。

二、Spring Security 如何使用 Session 维持认证状态(有状态会话)

在默认配置下,Spring Security 利用 HTTP Session 来存储用户的认证信息。这意味着一旦用户通过认证(例如通过表单登录),其认证状态会被保存到 Session 中,从而在后续的请求中无需重新认证。

(1)认证成功后的认证信息存储

当用户成功通过认证(例如通过表单登录或其他认证方式),Spring Security 会执行以下步骤:

  • 创建 Authentication 对象: 认证成功后,Spring Security 会生成一个已认证的 Authentication 对象,包含用户的详细信息和权限。

  • 存储到 SecurityContextHolder

    SecurityContext context = SecurityContextHolder.createEmptyContext();
    context.setAuthentication(authResult); // authResult 是已认证的 Authentication 对象
    SecurityContextHolder.setContext(context);
    
  • 存储到 HTTP Session: Spring Security 的 SecurityContextPersistenceFilter 会将 SecurityContextHolder 中的 SecurityContext 保存到 HTTP Session 中。这样,用户的认证状态在会话期间保持有效。

    // SecurityContextPersistenceFilter 内部逻辑示例
    HttpSession session = request.getSession(false);
    if (session != null) {session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context);
    }
    

(2)每次请求时加载认证信息

当用户在同一会话中发起新的请求时,Spring Security 会执行以下步骤:

  • HTTP Session 中加载 SecurityContextSecurityContextPersistenceFilter 会在请求开始时,从 HTTP Session 中提取存储的 SecurityContext 对象,并将其设置到 SecurityContextHolder 中。

    // SecurityContextPersistenceFilter 内部逻辑示例
    HttpSession session = request.getSession(false);
    if (session != null) {SecurityContext context = (SecurityContext) session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);if (context != null) {SecurityContextHolder.setContext(context);}
    }
    
  • 访问 SecurityContextHolder: 任何在处理请求的代码(如控制器、服务层、授权注解等)都可以通过 SecurityContextHolder.getContext().getAuthentication() 来获取当前用户的认证信息,无需重新认证。

(3)请求结束后的认证信息保存

请求处理完成后,SecurityContextPersistenceFilter 会将当前线程的 SecurityContext 再次保存回 HTTP Session,以确保认证信息在会话中持续有效。

// SecurityContextPersistenceFilter 内部逻辑示例
HttpSession session = request.getSession(false);
if (session != null) {session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, context);
}

三、相关组件详解

(1)SecurityContextHolder

  • 作用:是 Spring Security 用来存储 SecurityContext 的核心类。SecurityContext 中包含了当前用户的 Authentication 对象。

  • 存取方式:通过静态方法 SecurityContextHolder.getContext()SecurityContextHolder.setContext() 来获取和设置 SecurityContext

  • 存储策略:默认使用 ThreadLocal 存储,确保每个线程(即每个请求)都有自己的安全上下文(SecurityContext)

(2)SecurityContextPersistenceFilter

  • 作用:负责在每次请求开始时从 HTTP Session 中加载 SecurityContext,并在请求结束时将 SecurityContext 保存回 Session。

  • 执行顺序:位于过滤器链的较前位置,确保在认证和授权之前加载认证信息。

  • 配置:默认情况下,Spring Security 自动注册此过滤器。通常不需要手动配置,除非有特殊需求。

(3)HttpSessionSecurityContextRepository

  • 作用SecurityContextPersistenceFilter 使用的存储机制,负责将 SecurityContext 存储到 HTTP Session 中。

  • 配置:默认使用 HttpSessionSecurityContextRepository,但也可以自定义实现,比如无状态认证(详见后文)。

四、无状态认证与 Session 管理

尽管默认情况下 Spring Security 使用 Session 来维持认证状态,但在某些场景下(如 RESTful API 或微服务架构),可能更倾向于无状态认证方式(例如基于 JWT)。在这种情况下,可以配置 Spring Security 使其不依赖于 HTTP Session,而是通过每个请求携带的 Token 来进行认证。

配置无状态认证的做法
  • 禁用 Session 管理

    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()// 其他配置
    

    SessionCreationPolicy.STATELESS 表示 Spring Security 不会创建或使用 HTTP Session。

  • 移除 SecurityContextPersistenceFilter

    在无状态模式下,SecurityContextPersistenceFilter 不再需要,因为不使用 Session 来存储 SecurityContext。但通常通过设置 SessionCreationPolicy.STATELESS,框架会自动调整过滤器链。

  • 使用 Token 过滤器

    自定义一个过滤器(如 JwtAuthenticationFilter)来从每个请求中提取 Token(如 JWT),验证其有效性,并将认证信息设置到 SecurityContextHolder 中。

    public class JwtAuthenticationFilter extends OncePerRequestFilter {private final AuthenticationManager authenticationManager;private final JwtService jwtService;public JwtAuthenticationFilter(AuthenticationManager authenticationManager, JwtService jwtService) {this.authenticationManager = authenticationManager;this.jwtService = jwtService;}@Overrideprotected void doFilterInternal(HttpServletRequest request,HttpServletResponse response,FilterChain filterChain) throws ServletException, IOException {String authHeader = request.getHeader("Authorization");if (authHeader != null && authHeader.startsWith("Bearer ")) {String token = authHeader.substring(7);// 验证 Token 并构建 Authentication 对象Authentication auth = jwtService.parseToken(token);if (auth != null) {SecurityContextHolder.getContext().setAuthentication(auth);}}filterChain.doFilter(request, response);}
    }
    

五、会话保持的优缺点

优点

  • 简化认证流程:无需在每次请求中重复发送凭证,服务器通过 Session 维护用户状态。
  • 自动管理:Spring Security 自动处理 Session 中的认证信息加载与存储。

缺点

  • 扩展性限制:在分布式系统中,管理和同步 Session 可能变得复杂,需要额外的配置(如分布式 Session 存储)。
  • 资源消耗:每个活跃用户都占用服务器的 Session 资源,可能影响可扩展性。
  • 不适用于无状态服务:对于需要完全无状态的 RESTful API,更推荐使用基于 Token 的认证方式。

http://www.ppmy.cn/news/1556293.html

相关文章

双十二年终活动淘宝天猫接口获取攻略

引言 双十二作为电商行业的重要促销节点,对于商家和消费者而言,获取淘宝天猫的相关活动数据至关重要。本文将为您提供一份详细的攻略,介绍如何利用Python爬虫技术获取双十二年终活动淘宝天猫接口数据。 环境准备 在开始之前,请…

Java 模板方法模式:打造高复用性的商品上架模块

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…

【从零开始入门unity游戏开发之——C#篇06】变量类型转化和异常捕获

文章目录 一、变量类型转化1、什么是类型转换2、隐式转化相同类型之间的转换 3、显示转换3.1 括号强转语法示例注意 3.2 使用 Parse 和 TryParse 方法语法示例 3.3 使用 Convert 类进行转换语法示例 3.4 .ToString()其他类型转string语法示例 二、异常捕获1、基本语法结构2、使…

实景视频与模型叠加融合?

[视频GIS系列]无人机视频与与实景模型进行实时融合_无人机视频融合-CSDN博客文章浏览阅读1.5k次,点赞28次,收藏14次。将无人机视频与实景模型进行实时融合是一个涉及多个技术领域的复杂过程,主要包括无人机视频采集、实景模型构建、视频与模型…

Opencv之图像梯度处理和绘制图像轮廓

一、梯度处理的sobel算子函数 处理示意 Sobel 算子是一种常用的图像边缘检测方法,结合了一阶导数和高斯平滑,用于检测图像的梯度信息。 1、功能 Sobel 算子用于计算图像在 x 和 y 方向的梯度,主要功能包括: 强调图像中灰度值的…

【鸿睿创智开发板试用】在OpenHarmony 4.1环境下移植OpenCV示例

目录 引言 修改工程环境 配置OpenCV库和头文件 修改代码 CMakeList.txt文件 qrcodeInfo.decodes is possibly undefined. warning: backslash and newline separated by space [-Wbackslash-newline-escape] 运行 结语 引言 在前面的博文(【鸿睿创智开发板…

前端学习-Web API基本认知(二十)

目录 前言 变量声明 变量声明有三个 var let 和 const我们应该用那个呢? 简单来说以后声明变量我们优先使用哪个? Web API基本认知 作用和分类 作用 分类 什么是DOM DOM树 DOM树是什么 DOM对象 DOM对象 DOM的核心思想 总结 前言 第二更(量较少&…

Apache HTTP 服务器深度性能优化

引言 在前几篇文章中,我们讨论了基础和高级性能优化策略。现在,我们将深入探讨一些具体的优化实践,帮助您实现更精细的控制,并确保Apache服务器在各种复杂环境中都能保持最佳性能。 1. 细粒度的Apache配置调整 1.1 MPM参数微调…