深入浅出Spring Security

news2025/6/9 7:37:44

一、Spring Security基本组件

Spring Security的设计理念是提供一种可插拔的、高度可定制的安全服务。其核心功能依赖于以下几个关键组件:

  1. Authentication (认证):

    • 概念: 确认用户身份的过程,即验证“你是谁”。
    • 核心类: Authentication 接口,代表当前的认证信息,包含用户名、密码、权限等。UsernamePasswordAuthenticationToken 是最常见的实现。
    • 相关组件:
      • AuthenticationManager: 认证管理器接口,负责验证Authentication对象。其常用实现是ProviderManager
      • AuthenticationProvider: 认证提供者接口,ProviderManager内部维护一个AuthenticationProvider列表,每个提供者负责一种特定的认证方式(如用户名密码认证、OAuth认证等)。DaoAuthenticationProvider是最常用的实现,它从用户详情服务获取用户信息进行验证。
  2. Authorization (授权):

    • 概念: 确定认证后的用户是否有权限执行特定操作的过程,即验证“你能做什么”。
    • 核心类: AccessDecisionManager 接口,负责做出授权决策。AbstractAccessDecisionManager 是常用实现。
    • 相关组件:
      • GrantedAuthority: 授权接口,代表用户被授予的权限(如ROLE_USERROLE_ADMIN)。
      • SecurityMetadataSource: 安全元数据源,定义了哪些URL或方法需要哪些权限。
      • FilterSecurityInterceptor / MethodSecurityInterceptor: 安全拦截器,负责在请求到达控制器或方法执行前,根据SecurityMetadataSource和用户的GrantedAuthority进行权限校验。
  3. Web Security Filters (过滤器链):

    • Spring Security的核心工作是通过一系列过滤器在FilterChain中执行。最核心的是FilterChainProxy,它内部维护了一个过滤器链(FilterChain列表)。
    • 关键过滤器:
      • ChannelProcessingFilter: 强制协议(如HTTPS)。
      • ConcurrentSessionFilter: 处理并发会话控制。
      • SecurityContextPersistenceFilter: 在请求开始时加载SecurityContext,结束时保存。
      • UsernamePasswordAuthenticationFilter / DefaultLoginPageGeneratingFilter: 处理基于表单的认证。
      • BasicAuthenticationFilter: 处理HTTP Basic认证。
      • RequestCacheAwareFilter: 处理请求缓存。
      • SecurityContextHolderFilter (旧版概念,新版本整合): 确保安全上下文可用。
      • FilterSecurityInterceptor: 执行基于URL的访问控制。
      • ExceptionTranslationFilter: 捕获安全异常并转换为合适的响应(如跳转到登录页、返回403)。
  4. UserDetailsService:

    • 定义了一个从数据源(如数据库、内存)加载用户详细信息的方法 loadUserByUsername(String username)。返回UserDetails对象,包含用户名、密码、权限等信息。开发者需要实现这个接口来提供自己的用户数据加载逻辑。
  5. Security Context:

    • SecurityContextHolder 类持有当前线程的SecurityContextSecurityContext中包含当前的Authentication对象。通过它,应用中的任何代码都可以获取当前认证用户的信息。

二、Spring Security应用场景

Spring Security的应用场景非常广泛,几乎涵盖了Web应用安全的所有方面:

  1. 用户认证: 支持多种认证方式,如用户名/密码表单登录、HTTP Basic/Digest认证、OAuth2、JWT、SAML、CAS等第三方认证、Remember-Me功能等。
  2. 授权控制:
    • 基于URL的访问控制: 配置哪些URL路径需要登录,以及登录后需要哪些角色/权限才能访问。
    • 方法级安全: 使用注解(如@PreAuthorize@Secured)控制对Spring管理的Bean方法的访问。
    • 域对象安全: 对特定对象(如订单、用户信息)的CRUD操作进行权限控制。
  3. 会话管理: 并发会话控制(如同一用户只能有一个登录会话)、会话固定保护、会话超时处理。
  4. CSRF防护: 默认启用CSRF(跨站请求伪造)防护,保护应用免受此类攻击。
  5. 安全头部: 自动添加安全相关的HTTP头部,如X-Content-Type-OptionsX-Frame-Options等,增强应用安全性。
  6. 密码编码: 提供强大的密码编码器(如BCryptPasswordEncoder),安全地存储用户密码。

三、Spring Security执行流程(以基于表单的认证为例)

当用户访问一个需要认证的页面时,Spring Security的执行流程大致如下:

  1. 请求到达: 用户浏览器发送请求到服务器。
  2. 过滤器链处理: 请求首先经过FilterChainProxy,然后进入其内部的过滤器链。
  3. 安全上下文检查: SecurityContextPersistenceFilter检查当前线程是否有SecurityContext(即用户是否已认证)。如果没有,则创建一个空的。
  4. 路径匹配与拦截: FilterSecurityInterceptor根据配置的安全规则(如antMatchers("/admin/**").hasRole("ADMIN")),判断当前请求路径是否需要认证以及需要哪些权限。
  5. 认证检查: 如果用户未认证(SecurityContext中没有有效的Authentication),ExceptionTranslationFilter会捕获这个情况,并决定如何处理:
    • 如果是登录请求(如/login),则允许请求继续。
    • 如果不是登录请求,则根据配置(通常是formLogin()配置)将用户重定向到登录页面(由DefaultLoginPageGeneratingFilter或自定义的登录页处理)。
  6. 登录处理: 用户填写表单并提交登录请求。
  7. 认证过滤器处理: UsernamePasswordAuthenticationFilter拦截到登录请求,从请求中提取用户名和密码。
  8. 认证提供者验证: Filter将用户名和密码封装成Authentication对象(通常是UsernamePasswordAuthenticationToken的不完整形式,只有用户名),然后提交给AuthenticationManager(通常是ProviderManager)。
  9. 用户详情加载: ProviderManager会委托给内部的AuthenticationProvider(如DaoAuthenticationProvider),该提供者会调用UserDetailsServiceloadUserByUsername方法,从数据库等地方加载完整的用户信息(包括密码和权限)。
  10. 密码匹配: AuthenticationProvider使用配置的PasswordEncoder比较用户提交的密码和从UserDetailsService加载的密码是否一致。
  11. 认证结果:
    • 成功: 如果密码匹配成功,AuthenticationProvider会创建一个完整的、已认证的Authentication对象(包含用户名、密码、权限等),并标记为已认证(setAuthenticated(true))。这个对象被传递回AuthenticationManager,然后存储到SecurityContext中。SecurityContextPersistenceFilter在请求结束时将其保存(通常是放入Session)。
    • 失败: 如果密码不匹配或其他原因导致认证失败,会抛出AuthenticationExceptionExceptionTranslationFilter会捕获该异常,通常返回一个错误信息给用户(如登录页显示“用户名或密码错误”)。
  12. 后续请求: 用户再次访问受保护的资源时,SecurityContextPersistenceFilter会从Session中恢复SecurityContext,后续的FilterSecurityInterceptor就能根据其中已认证的Authentication对象进行授权判断。

四、常见业务问题案例

在使用Spring Security的过程中,开发者可能会遇到一些常见的问题:

  1. 问题: 登录成功后,访问受保护资源仍然被重定向到登录页。

    • 可能原因:
      • 密码编码器配置错误:UserDetailsService返回的UserDetails中的密码没有使用与登录时相同的PasswordEncoder进行编码。
      • SecurityContext没有正确保存或恢复:检查SecurityContextPersistenceFilter的配置。
      • 会话问题:浏览器禁用了Cookie或Session失效。
      • 权限配置错误:虽然登录成功,但用户没有访问目标URL所需的权限。
    • 排查思路: 检查密码编码器配置一致性,检查安全过滤器链配置,查看控制台日志,检查浏览器开发者工具的网络请求和Cookie。
  2. 问题: 使用@PreAuthorize注解进行方法级权限控制时,注解不生效。

    • 可能原因:
      • 忘记启用方法级安全:在配置类上缺少@EnableGlobalMethodSecurity(prePostEnabled = true)@EnableMethodSecurity(prePostEnabled = true)(Spring Security 5+)。
      • MethodSecurityInterceptor没有正确配置或加入过滤器链。
      • 表达式语法错误:检查@PreAuthorize中的SpEL表达式是否正确,特别是角色前缀(如hasRole('ADMIN')默认会自动添加ROLE_前缀,如果数据库存储的是ADMIN而非ROLE_ADMIN,需要调整)。
    • 排查思路: 检查配置类上的注解,确认MethodSecurityInterceptor的Bean定义,仔细核对SpEL表达式和角色名称。
  3. 问题: 并发会话控制不生效,同一用户可以在多个浏览器/标签页同时登录。

    • 可能原因:
      • 没有启用或正确配置并发会话控制:检查sessionManagement().maximumSessions()配置。
      • Session ID生成或管理有问题。
      • 前端可能存在多个Session ID被同时使用的情况。
    • 排查思路: 检查sessionManagement()配置,查看日志中关于会话创建和失效的信息,确认是否按照预期阻止了新的会话。
  4. 问题: CSRF防护导致POST请求失败,返回403。

    • 可能原因:
      • 前端没有正确包含CSRF Token:对于非简单请求(如POST、PUT、DELETE等),需要在请求头或请求体中携带CSRF Token。
      • 前端获取的Token与后端验证的Token不匹配:可能是Token过期或获取方式错误。
    • 排查思路: 检查前端代码是否从X-CSRF-TOKEN响应头或_csrf隐藏字段获取Token,并正确地在请求中发送。使用浏览器开发者工具检查请求头。
  5. 问题: 自定义登录页无法正常跳转或表单提交后无响应。

    • 可能原因:
      • 自定义登录页URL配置错误:formLogin().loginPage("/myLogin")中的路径是否正确。
      • 登录处理URL配置错误:默认是/login,如果修改了(如loginProcessingUrl("/doLogin")),前端表单的action属性必须与之匹配。
      • CSRF Token问题:自定义登录页也需要处理CSRF Token。
      • 前端路由或框架(如React, Vue)与Spring Security的交互问题。
    • 排查思路: 仔细核对自定义登录页的配置,检查前端表单的action和CSRF处理,确保URL匹配。对于前端框架,可能需要特殊处理路由跳转和表单提交。

五、总结

Spring Security是一个功能强大且复杂的框架,但它极大地简化了Web应用安全性的实现。理解其核心组件、熟悉常见应用场景、掌握基本执行流程,并学会排查常见问题,是熟练使用它的关键。虽然配置起来可能有些繁琐,但其带来的安全性和可维护性是值得投入时间和精力去学习的。希望这篇博客能帮助你更好地理解和应用Spring Security,为你的应用构建坚固的安全防线。

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

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

相关文章

基于51单片机的红外防盗及万年历仿真

目录 具体实现功能 设计介绍 资料内容 全部内容 资料获取 具体实现功能 具体功能: (1)实时显示年、月、日、时、分、秒、星期信息; (2)红外传感器(仿真中用按键模拟)检测是否有…

【飞腾AI加固服务器】全国产化飞腾+昇腾310+PCIe Switch的AI大模型服务器解决方案

以下是全国产化飞腾AI加固服务器采用飞腾昇腾PCIe Switch解决方案: 🖥️ 一、硬件架构亮点 ‌国产算力双擎‌ ‌飞腾处理器‌:搭载飞腾FT2000/64核服务器级CPU(主频1.8-2.2GHz),支持高并发任务与复杂计算&a…

应用层协议:HTTPS

目录 HTTPS:超文本传输安全协议 1、概念 2、通信过程及关键技术 2.1 通信过程 1> TLS握手协商(建立安全通道) 2> 加密数据传输 2.2 关键技术 1> 对称加密算法 2> 非对称加密 3> 对称加密和非对称加密组合 4> 数…

【ArcGIS技巧】—村庄规划规划用地规划状态字段生成工具

"国土空间规划后续也是走向数据治理,数据建库已经是涉及到城市规划、建筑、市政、农业、地理信息、测绘等等方方面面。不得不说以后数据库建设跟维护,是很多专业的必修课。小编就湖南省的村庄规划建库过程中规划用地用海中规划状态字段写了个小工具…

【PCIe总线】-- inbound、outbound配置

PCI、PCIe相关知识整理汇总 【PCIe总线】 -- PCI、PCIe相关实现 由之前的PCIe基础知识可知,pcie的组成有:RC(根节点)、siwtch(pcie桥)、EP(设备)。 RC和EP,以及EP和EP能…

分布式锁实战:Redisson vs. Redis 原生指令的性能对比

分布式锁实战:Redisson vs. Redis 原生指令的性能对比 引言 在DIY主题模板系统中,用户可自定义聊天室的背景、图标、动画等元素。当多个运营人员或用户同时修改同一模板时,若没有锁机制,可能出现“甲修改了背景色,乙…

react+taro 开发第五个小程序,解决拼音的学习

1.找一个文件夹 cmd 2.taro init 3.vscode 找开该文件夹cd help-letters 如:我的是(base) PS D:\react\help-letters> pnpm install 4.先编译一下吧。看下开发者工具什么反应。 pnpm dev:weapp 5.开始规则。我用cursor就是不成功。是不是要在这边差不多了&…

kafka(windows)

目录 介绍 下载 配置 测试 介绍 Kafka是一个分布式流媒体平台,类似于消息队列或企业信息传递系统。 下载 Kafka对于Zookeeper是强依赖,所以安装Kafka之前必须先安装zookeeper 官网:Apache Kafka 下载此安装包并解压 配置 新建log…

基于安卓的文件管理器程序开发研究源码数据库文档

摘 要 伴随着现代科技的发展潮流,移动互联网技术快速发展,各种基于通信技术的移动终端设备做的也越来越好了,现代智能手机大量的进入到了我们的生活中。电子产品的各种软硬技术技术的发展,操作系统的不断更新换代,谷歌…

EMC VNXe 存储系统日志收集方法

写在前面 有朋友找来看看VNXe的故障,这种问题总是要收集日志,顺便这里也分享给大家。 注意,VNXe和VNX 属于完全不同的产品,不要看名字很类似,操作系统已经完全重构了,如果说是否有联系,大概就…

从“人找政策”到“政策找人”:智能退税ERP数字化重构外贸生态

离境退税新政核心内容与外贸企业影响 (一)政策核心变化解析 退税商店网络扩容 新政明确鼓励在大型商圈、旅游景区、交通枢纽等境外旅客聚集地增设退税商店,并放宽备案条件至纳税信用M级企业。以上海为例,静安区计划新增1000家退…

以人类演示视频为提示,学习可泛化的机器人策略

25年5月来自清华大学、上海姚期智研究院和星动纪元(RoboEra)公司的论文“Learning Generalizable Robot Policy with Human Demonstration Video as a Prompt”。 最近的机器人学习方法通​​常依赖于从通过遥操作收集的大量机器人数据集中进行模仿学习…

SOC-ESP32S3部分:36-适配自己的板卡

飞书文档https://x509p6c8to.feishu.cn/wiki/RP4UwPrsKi4xuQkKLAAcKxD3n1b 如果你自己画了PCB板,需要把自己绘制的板卡配置小智AI工程,可以参考此文档。 下载源码 克隆或下载源码到本地,这里以1.5.5为例,大家可以自行修改其它版…

LLMs 系列科普文(8)

八、模型的自我认知 接下来我们聊聊另一种问题,即模型的自我认知。 网上经常经常可以看到人们会问大语言模型一些关于认知方面的问题,比如“你是什么模型?谁创造了你?” 说实话,其实这个问题有点无厘头。 之所以这么…

机器学习基础相关问题

机器学习相关的基础问题 K-means是否一定会收敛 K-means是否一定会收敛 K-means算法在有限步数内一定会收敛,但收敛到的可能是局部最优解而非全局最优解。以下是详细分析: K-means 的优化目标是最小化 样本到其所归属簇中心的距离平方和(SSE…

验证负载均衡与弹性伸缩

什么是弹性伸缩(Auto Scaling)? 弹性伸缩是指 云计算平台根据实时负载自动调整计算资源(如服务器实例、容器Pod)数量,以确保系统在高峰时保持稳定,在低谷时节省成本。 什么时候会触发弹性伸缩&…

Three.js中AR实现详解并详细介绍基于图像标记模式AR生成的详细步骤

文档地址 Three.js中AR实现详解 以下是Three.js中实现AR功能的详细解析,涵盖技术原理、实现步骤、核心组件及优化策略: 🧩 一、技术基础 AR.js框架的核心作用 AR.js是Three.js实现AR的基石,提供以下核心能力: 多模…

GeoBoundaries下载行政区划边界数据(提供中国资源shapefile)

要下载山东省济南市各个区的行政区划边界数据,你可以通过 geoBoundaries 提供的数据来实现。下面是详细步骤,包括网页操作和可选的 Python 自动化方式。 目录 ✅ 一、通过 geoBoundaries 官网手动下载1. 打开官网:2. 查找中国数据&#xff1a…

大模型如何选型?嵌入模型如何选型?

欢迎来到啾啾的博客🐱。 记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。 有很多很多不足的地方,欢迎评论交流,感谢您的阅读和评论😄。 目录 引言模型优劣认知与模型选择大模型(L…

开源大模型网关:One API实现主流AI模型API的统一管理与分发

以下是对One API的简单介绍: One API是一个使用go语言开发的大语言模型 API 管理与分发系统支持Docker一键快速部署,且资源占用小,高性能开箱支持多平台大模型快速接入,包括OpenAI、Gemini、xAI、Grop、Anthropic Claude、Ollama…