Spring Security与Spring Boot集成原理

news2025/5/21 3:47:38

Spring Security依赖的是过滤器机制,首先是web容器例如tomcat作为独立的产品,本身有自己的一套过滤器机制用来处理请求,那么如何将tomcat接收到的请求转入到Spring Security的处理逻辑呢?spring充分采用了tomcat的拓展机制提供了tomcat过滤器的一个拓展,也就是中间加了一个适配器。这样当请求过来之后,请求经过web容器的过滤器的时候就会进入spring的过滤器流程,从而进入security的过滤器流程。

Tomcat的拓展机制

根据servlet规范:

从Servlet3.0开始,在ServletContext中添加了方法支持在使用编程的方式来自定义servlet,filter和url pattern。有两种方式来定义这些:

  1. contexInitialized method of a ServletContextListener implementation;
  2. the onStartup method of a ServletContainerInitializer implementation;

我们来看通过外部ServletContainerInitializer实现的加载方式,官方定义:在服务启动的时候会通过java的spi机制去查找ServletContainerInitializer类,并且每个应用在启动的时候会实例化ServletContainerInitializer。我们需要将实现放到META-INF/services/javax.servlet.ServletContainerInitializer文件中。

For each application, an instance of the ServletContainerInitializer is created by the container at application startup time.

ServletContainerInitializer会在服务启动的时候并且所有的servlet监听器调用之前被调用。

在文档中还描述了一个重要的注解就是:HandlesType,这个注解的作用是:在ServletContainerInitializer 的 onStartup 方法会被调用的时候,会传入一个 Set 集合,该集合包含的类要么是扩展/实现了初始化器所感兴趣(通过 @HandlesTypes 注解指定)的类,要么是带有通过 @HandlesTypes 注解指定的任何类作为注解的类。

The onStartup method of the ServletContainerInitializer is called with a Set of Classes that either extend / implement the classes that the initializer expressed interest in or if it is annotated with any of the classes specified via the @HandlesTypes annotation.

在了解了上面的前提之后,我们来看Spring进行的拓展,查看spring-web中文件META-INF/services/javax.servlet.ServletContainerInitializer会发现里面有一个实现类:org.springframework.web.SpringServletContainerInitializer,而这也正是一切的开始。

SpringServletContainerInitializer

@HandlesTypes(WebApplicationInitializer.class)
public class SpringServletContainerInitializer implements ServletContainerInitializer {
    	@Override
	public void onStartup(@Nullable Set<Class<?>> webAppInitializerClasses, ServletContext servletContext)
			throws ServletException {
            ......
        }
}

我们首先注意到在上面的实现中,@HandlesTypes注解指定的是WebApplicationInitializer类,因此在onStartup方法的参数webAppInitializerClasses中我们就能获取到所有该接口的实现类。之后便是通过反射进行实例化和执行所有WebApplicationInitializer实现类的onStartup方法。

查看WebApplicationInitializer接口的实现类可以看到:

由于引了包的缘故,这里看到了web、webmvc和security下面的实现。这里我们看到了熟悉的ContextLoader,当还在使用web.xml集成配置spring的时候,我们配置过<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>,在这里使用AbstractContextLoaderInitializer以编程的方式实现了同样的效果。同样的道理还有AbstractDispatcherServletInitializer,也使用编程的方式替换掉了我们的web.xml配置。

<servlet>
<servlet-name>app</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

那Spring Security的实现呢,我们还看到了AbstractSecurityWebApplicationInitializer这个实现类?

AbstractSecurityWebApplicationInitializer

tomcat容器在执行的时候会执行过滤器链FilterChain。同时为拓展filter提供了标准,我们可以通过实现Filter接口来注册我们自己的Filter到FilterChain中,但是tomcat容器不会感知到spring容器中的Filter实例。
因此spring提供了一个Filter的实现:DelegatingFilterProxy ,从而将spring中的过滤器的逻辑加入到tomcat容器中。

我们查看Spring Security的官网,对这个架构图不会陌生:

为了和spring的集成,Spring Security利用spring提供的过滤器的拓展点,提供了一个Spring Security的统一的入口:FilterChainProxy,在集成之后执行过滤器的时候会通过:tomcat Filter->spring filter->spring security filter调用链路进行调用。

onStartup

我们来看一下AbstractSecurityWebApplicationInitializeronStartup方法的实现逻辑:

insertSpringSecurityFilterChain方法的实现:

在这里创建了一个DelegatingFilterProxy对象,并且传递的filterName是DEFAULT_FILTER_NAME,这个常量是“springSecurityFilterChain”。这里需要注意的是这个传递的是filterName是一个bean名称。
在第一次接收到请求的时候,在doFilter方法中会使用单例模式从spring容器中获取bean名称的实例,生成一个唯一的Filter对象。通过调试最后得到的是:FilterChainProxy对象。

从这里我们可以知道,如果我们拓展一套自己的过滤器逻辑,则可以把DelegatingFilterProxy当作入口,filterName参数使用我们自己的filter bean名称就可以了。

总结

在servlet3.0之后,我们可以将之前web.xml中的配置内容通过编程式的方式来实现。Spring充分利用了这一拓展,提供了ServletContainerInitializer接口的实现类SpringServletContainerInitializer来在启动的时候初始化所有的WebApplicationInitializer。

Spring Security使用了这个拓展方式,将请求通过tomcat Filter->spring filter->spring security filter这样的链路,转入到自己的处理逻辑当中。

对于我们自定义的过滤器也可以通过DelegatingFilterProxy作为接入点,将请求引入进来。

参考

  • servlet-spec-6.1

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

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

相关文章

VScode各文件转化为PDF的方法

文章目录 代码.py文件.ipynb文本和代码夹杂的文件方法 1:使用 VS Code 插件(推荐)步骤 1:安装必要插件步骤 2:安装 `nbconvert`步骤 3:间接导出(HTML → PDF)本文遇见了系列错误:解决方案:问题原因步骤 1:降级 Jinja2 至兼容版本步骤 2:确保 nbconvert 版本兼容替代…

Vue3学习(组合式API——Watch侦听器、watchEffect()详解)

目录 一、Watch侦听器。 &#xff08;1&#xff09;侦听单个数据。 &#xff08;2&#xff09;侦听多个数据。&#xff08;数组写法&#xff1f;&#xff01;&#xff09; &#xff08;3&#xff09;immediate参数。(立即执行回调) &#xff08;3&#xff09;deep参数。(深层监…

【node.js】安装与配置

个人主页&#xff1a;Guiat 归属专栏&#xff1a;node.js 文章目录 1. Node.js简介1.1 Node.js的特点1.2 Node.js架构 2. Node.js安装2.1 下载和安装方法2.1.1 Windows安装2.1.2 macOS安装2.1.3 Linux安装 2.2 使用NVM安装和管理Node.js版本2.2.1 安装NVM2.2.2 使用NVM管理Node…

《AI大模型应知应会100篇》第62篇:TypeChat——类型安全的大模型编程框架

第62篇&#xff1a;TypeChat——类型安全的大模型编程框架 摘要 在构建 AI 应用时&#xff0c;一个常见的痛点是大语言模型&#xff08;LLM&#xff09;输出的不确定性与格式不一致问题。开发者往往需要手动解析、校验和处理模型返回的内容&#xff0c;这不仅增加了开发成本&a…

EdgeShard:通过协作边缘计算实现高效的 LLM 推理

(2024-05-23) EdgeShard: Efficient LLM Inference via Collaborative Edge Computing (EdgeShard:通过协作边缘计算实现高效的 LLM 推理) 作者: Mingjin Zhang; Jiannong Cao; Xiaoming Shen; Zeyang Cui;期刊: (发表日期: 2024-05-23)期刊分区:本地链接: Zhang 等 - 2024 …

火山 RTC 引擎9 ----集成 appkey

一、集成 appkey 1、网易RTC 初始化过程 1&#xff09;、添加头文件 实现互动直播 - 互动直播 2.0网易云信互动直播产品的基本功能包括音视频通话和连麦直播&#xff0c;当您成功初始化 SDK 之后&#xff0c;您可以简单体验本产品的基本业务流程&#xff0c;例如主播加入房间…

Adminer:一个基于Web的轻量级数据库管理工具

Adminer 是一个由单个 PHP 文件实现的免费数据库管理工具&#xff0c;支持 MySQL、MariaDB、PostgreSQL、CockroachDB、SQLite、SQL Server、Oracle、Elasticsearch、SimpleDB、MongoDB、Firebird、Clickhouse 等数据库。 Adminer 支持的主要功能如下&#xff1a; 连接数据库服…

RK3568下QT实现按钮切换tabWidget

运行效果: 在 Qt 应用程序开发过程中,TabWidget 是一种非常实用的 UI 组件,它能够以选项卡的形式展示多个页面内容,帮助我们有效组织和管理复杂的界面布局。而在实际使用时,常常会有通过按钮点击来切换 TabWidget 页面的需求,本文将通过一个完整的示例,详细介绍如何在 Q…

2025 OceanBase 开发者大会全议程指南

5 月 17 日&#xff0c;第三届 OceanBase 开发者大会将在广州举办。 我们邀请数据库领军者与AI实践先锋&#xff0c;与开发者一起探讨数据库与 AI 协同创新的技术趋势&#xff0c;面对面交流 OceanBase 在 TP、AP、KV 及 AI 能力上的最新进展&#xff0c;深度体验“打破技术栈…

day017-磁盘管理-实战

文章目录 1. 硬盘命名规则2. 添加硬盘2.1 查看硬盘名称 3. 硬盘分区3.1 分区命名规则&#xff1a;mbr分区表格式3.2 创建分区&#xff1a;fdisk3.2.1 fdisk -l&#xff1a;查看硬盘及分区信息3.2.2 fdisk /dev/sdc :为该硬盘分区3.2.3 创建扩展分区和逻辑分区3.2.4 保存设置并退…

【成品设计】STM32和UCOS-II的项目

项目1&#xff1a;《基于STM32和UCOS-II的水质监测系统》 Ps&#xff1a;分为带系统版本和不带系统版本&#xff0c;功能都一样。 功能说明&#xff1a; 1. 单片机主控&#xff1a;STM32F103C8T6单片机作为核心控制。 2. 酸碱度传感器&#xff1a;实时采集当前PH值。 3. 水质…

Ngrok 配置:实现 Uniapp 前后端项目内网穿透

文章目录 一、下载并安装 ngrok二、配置 ngrok Authtoken三、启动本地 uniapp 项目四、使用 ngrok 暴露本地服务五、通过公网 URL 访问项目六、后端API项目的穿透问题排查 (uni-app 后端 API 示例)交互流程图示 七、ngrok Web 界面 (本地监控)八、停止 ngrok总结 ngrok 是一款…

鸿蒙ArkUI体验:Hexo博客客户端开发心得

最近部门也在跟进鸿蒙平台的业务开发&#xff0c;自己主要是做 Android 开发&#xff0c;主要使用 Kotlin/Java 语言。&#xff0c;需要对新的开发平台和开发模式进行学习&#xff0c;在业余时间开了个项目练手&#xff0c;做了个基于 Hexo 博客内容开发的App。鸿蒙主要使用Ark…

鸿蒙NEXT开发动画案例10

1.创建空白项目 2.Page文件夹下面新建Spin.ets文件&#xff0c;代码如下&#xff1a; interface TranslateOffset {x?:numbery?:number } /*** SpinKit动画组件 - SpinTen* author: CSDN-鸿蒙布道师* since: 2025/05/16*/ ComponentV2 export struct SpinTen {Require Para…

【Linux】Linux安装并配置Redis

目录 1.安装 2.启动服务 3.配置 3.1.绑定地址 3.2.保护模式 3.3.持久化选项 3.3.1.RDB 持久化 3.3.2.AOF 持久化 3.3.3.如何选择 1.安装 Redis 可以从默认的 CentOS 软件仓库中安装。运行以下命令来安装 Redis sudo dnf install redis -y 响应如下 2.启动服务 安装完成后&…

【11408学习记录】考研英语辞职信写作三步法:真题精讲+妙句活用+范文模板

应聘信 英语写作2005年考研英语真题小作文写作思路第一段第二段妙句7 9妙句11补充3补充4 第三段 妙句成文 每日一句词汇第一步&#xff1a;找谓语第二步&#xff1a;断句第三步&#xff1a;简化主句原因状语从句 英语 写作 2005年考研英语真题小作文 Directions:​​ Two m…

《黑马前端ajax+node.js+webpack+git教程》(笔记)——node.js教程+webpack教程(nodejs教程)

黑马程序员前端AJAX入门到实战全套教程&#xff0c;包含学前端框架必会的&#xff08;ajaxnode.jswebpackgit&#xff09;&#xff0c;一套全覆盖 文章目录 Node.js与Webpack-01.Node.js入门定义和作用什么是前端工程化&#xff1f;&#xff08;离不开node.js&#xff09;Node.…

Flink 快速入门

本文涉及到大量的底层原理知识&#xff0c;包括运行机制图解都非常详细&#xff0c;还有一些实战案例&#xff0c;所以导致本篇文章会比较长&#xff0c;内容比较多&#xff0c;由于内容太多&#xff0c;很多目录可能展示不出来&#xff0c;需要去细心的查看&#xff0c;非常适…

阻塞队列:线程安全与生产者消费者模型解析

一、阻塞队列 阻塞队列就是基于普通队列做出扩展 1.线程安全的 如果针对一个已经满了的队列进行入队列&#xff0c;此时入队列操作就会阻塞&#xff0c;一直阻塞到队列不满&#xff08;其他线程出队列元素&#xff09;之后 如果针对一个已经空了的队列进行出队列&#xff0c…

【入门|Docker】基础知识扫盲:什么是 Docker?

文章目录 基础知识扫盲&#xff1a;什么是 Docker&#xff1f;Docker 是什么&#xff1f;Docker 核心组件Docker 与虚拟机的区别Docker 在现代开发中的核心角色Docker 的局限性 基础知识扫盲&#xff1a;什么是 Docker&#xff1f; 最近打算开始系统性地学习与云计算相关的技术…