FantasticMao 技术笔记
BlogGitHub
  • README
  • C & Unix
    • C
      • 《C 程序设计语言》笔记
      • C 语言中的陷阱
      • CMake 示例
      • GNU make
      • LLVM Clang
      • Nginx 常用模块
      • Vim 常用命令
    • Unix-like
      • 《深入理解计算机系统》笔记
      • 《UNIX 环境高级编程》笔记 - UNIX 基础知识
      • 《UNIX 环境高级编程》笔记 - 文件 IO
      • 《UNIX 环境高级编程》笔记 - 标准 IO 库
      • 《鳥哥的 Linux 私房菜》笔记 - 目录配置
      • 《鳥哥的 Linux 私房菜》笔记 - 认识与学习 bash
      • 《鳥哥的 Linux 私房菜》笔记 - 任务管理
      • OpenWrt 中的陷阱
      • iptables 工作机制
  • Go
    • 《A Tour of Go》笔记
    • Go vs C vsJava
    • Go 常用命令
    • Go 语言中的陷阱
  • Java
    • JDK
      • 《Java 并发编程实战》笔记 - 线程池的使用
      • 设计模式概览
      • 集合概览
      • HashMap 内部算法
      • ThreadLocal 工作机制
      • Java Agent
    • JVM
      • 《深入理解 Java 虚拟机》笔记 - Java 内存模型与线程
      • JVM 运行时数据区
      • 类加载机制
      • 垃圾回收算法
      • 引用类型
      • 垃圾收集算法
      • 垃圾收集器
    • Spring
      • Spring IoC 容器扩展点
      • Spring Transaction 声明式事务管理
      • Spring Web MVC DispatcherServlet 工作机制
      • Spring Security Servlet 实现原理
    • 其它
      • 《Netty - One Framework to rule them all》演讲笔记
      • Hystrix 设计与实现
  • JavaScript
    • 《写给大家看的设计书》笔记 - 设计原则
    • 《JavaScript 权威指南》笔记 - jQuery 类库
  • 数据库
    • ElasticSearch
      • ElasticSearch 概览
    • HBase
      • HBase 数据模型
    • Prometheus
      • Prometheus 概览
      • Prometheus 数据模型和指标类型
      • Prometheus 查询语法
      • Prometheus 存储原理
      • Prometheus vs InfluxDB
    • Redis
      • 《Redis 设计与实现》笔记 - 简单动态字符串
      • 《Redis 设计与实现》笔记 - 链表
      • 《Redis 设计与实现》笔记 - 字典
      • 《Redis 设计与实现》笔记 - 跳跃表
      • 《Redis 设计与实现》笔记 - 整数集合
      • 《Redis 设计与实现》笔记 - 压缩列表
      • 《Redis 设计与实现》笔记 - 对象
      • Redis 内存回收策略
      • Redis 实现分布式锁
      • Redis 持久化机制
      • Redis 数据分片方案
      • 使用缓存的常见问题
    • MySQL
      • 《高性能 MySQL》笔记 - Schema 与数据类型优化
      • 《高性能 MySQL》笔记 - 创建高性能的索引
      • 《MySQL Reference Manual》笔记 - InnoDB 和 ACID 模型
      • 《MySQL Reference Manual》笔记 - InnoDB 多版本
      • 《MySQL Reference Manual》笔记 - InnoDB 锁
      • 《MySQL Reference Manual》笔记 - InnoDB 事务模型
      • B-Tree 简述
      • 理解查询执行计划
  • 中间件
    • gRPC
      • gRPC 负载均衡
    • ZooKeeper
      • ZooKeeper 数据模型
    • 消息队列
      • 消息积压解决策略
      • RocketMQ 架构设计
      • RocketMQ 功能特性
      • RocketMQ 消息存储
  • 分布式系统
    • 《凤凰架构》笔记
    • 系统设计思路
    • 系统优化思路
    • 分布式事务协议:二阶段提交和三阶段提交
    • 分布式系统的技术栈
    • 分布式系统的弹性设计
    • 单点登录解决方案
    • 容错,高可用和灾备
  • 数据结构和算法
    • 一致性哈希
    • 布隆过滤器
    • 散列表
  • 网络协议
    • 诊断工具
    • TCP 协议
      • TCP 报文结构
      • TCP 连接管理
由 GitBook 提供支持
在本页
  • Javax Servlet - Filters
  • Spring Web MVC - DelegatingFilterProxy
  • Spring Security - FilterChainProxy
  • Spring Security - SecurityFilterChain
  • 总结
  • 参考资料
  1. Java
  2. Spring

Spring Security Servlet 实现原理

最后更新于1年前

Spring Security 对 Servlet 的支持是基于 javax.servlet.Filter 实现的。

Javax Servlet - Filters

在 Servlet 应用中,一次 HTTP 请求的分层处理如下图所示:

Client 给应用发送一个 HTTP 请求,Servlet 容器会创建一个包含 Filter 和 Servlet 的 FilterChain,FilterChain 会基于请求 URI 中的 path 部分来处理对应的 HttpServletRequest。在 Spring MVC 应用中, Servlet 具体是 org.springframework.web.servlet.DispatcherServlet。

一个 Servlet 最多可以处理一次 HttpServletRequest 和 HttpServletResponse,但是 Filter 可以被使用多次,可以用于:

  • 防止下游的 Filter 或者 Servlet 被调用;

  • 修改下游的 Filter 和 Servlet 所使用的 HttpServletRequest 或者 HttpServletResponse。

Spring Web MVC - DelegatingFilterProxy

Spring Web MVC 提供了一个名为 DelegatingFilterProxy 的 Filter 实现类,用于连接 Servlet 容器和 Spring 的 ApplicationContext。Servlet 容器只允许注册标准的 Filter 实现类,不能注册 Spring IoC 容器中定义的 Bean。DelegatingFilterProxy 实现了 Filter 接口,可以被标准的 Servlet 容器所注册,并且 可以把 Filter 的实现逻辑委托给一个实现了 Filter 接口的 Spring Bean。

DelegatingFilterProxy 的工作机制如下图所示:

DelegatingFilterProxy 会在 Spring ApplicationContext 中查找 Bean Filter0,然后调用 Bean Filter0 中的 Filter 实现逻辑。

Spring Security - FilterChainProxy

Spring Security 提供了一个名为 FilterChainProxy 的特殊的 Filter 实现类,可以通过 SecurityFilterChain 来委托多个 Filter 的实例。FilterChainProxy 属于 Spring Bean,会被包装在 DelegatingFilterProxy 中。

FilterChainProxy 的工作机制如下图所示:

Spring Security - SecurityFilterChain

FilterChainProxy 使用 SecurityFilterChain 来 确定在当前的 HTTP 请求中应该调用那些 Spring Security 相关的 Filter。

SecurityFilterChain 的工作机制如下图所示:

SecurityFilterChain 中 Spring Security 相关的 Filter 都属于 Spring Bean,会被注册到 FilterChainProxy 而不是 DelegatingFilterProxy 中。选择将 Filter 注册到 FilterChainProxy,而不是直接注册到 Servlet 容器或者 DelegatingFilterProxy 会有许多好处。首先,FilterChainProxy 为 Spring Security 对 Servlet 的所有支持提供了一个起点。因此,如果开发者在尝试解决应用中 Spring Security 相关问题的时候,可以在 FilterChainProxy 中添加一个断点然后开始 debug。

其次,FilterChainProxy 对于 Spring Security 的工作机制来说非常重要,它还被设计成 可以执行一些辅助性质的任务。例如,FilterChainProxy 会清除 SecurityContext 中的数据,用于避免内存泄漏;FilterChainProxy 还会通过使用 Spring Security 的 HttpFirewall 来保护应用免受某些类型的攻击。

另外,FilterChainProxy 提供了更大的灵活性,用于确定应该在何时需要调用 SecurityFilterChain。在 Servlet 容器中,仅会单独根据 URL 是否匹配来确定是否需要调用 Filter。然而,通过使用 RequestMatcher 接口,FilterChainProxy 可以基于 HttpServletRequest 中的任何内容来确定是否需要调用 Filter。

总结

WebSecurityConfiguration 创建并配置 WebSecurity,WebSecurity 用于构建 FilterChainProxy。

参考资料

Spring Security - Servlet Security
filter chain
将 Filter 的实现委托给一个 Spring Bean
delegating filter proxy
filter chain proxy
security filter chain
清除 SecurityContext 中的数据,用于避免内存泄漏
使用 HttpFirewall 来保护应用免受某些类型的攻击
使用 RequestMatcher 接口来确定是否需要调用 Filter