FilterChainProxy

简介: 本文通过源码分析Spring Security中的`FilterChainProxy`,揭示其如何整合多个过滤器。结合调试截图与代码注释,逐步解析请求处理流程:从`doFilter`入口到`SecurityFilterChain`匹配,最终将十五个过滤器封装执行,验证了过滤器链的构建与调用机制。
public class FilterChainProxy extends GenericFilterBean {
    private static final Log logger = LogFactory.getLog(FilterChainProxy.class);
    private static final String FILTER_APPLIED =
    FilterChainProxy.class.getName().concat(".APPLIED");
    private List<SecurityFilterChain> filterChains;
    private FilterChainProxy.FilterChainValidator filterChainValidator;
    private HttpFirewall firewall;
    //咿!?可以通过一个叫SecurityFilterChain的对象实例化出一个FilterChainProxy对象
    //这FilterChainProxy又是何方神圣?会不会是真正的过滤器链对象呢?先留着这个疑问!
    public FilterChainProxy(SecurityFilterChain chain) {
        this(Arrays.asList(chain));
    }
    //又是SecurityFilterChain这家伙!嫌疑更大了!
    public FilterChainProxy(List<SecurityFilterChain> filterChains) {
        this.filterChainValidator = new FilterChainProxy.NullFilterChainValidator();
        this.firewall = new StrictHttpFirewall();
        this.filterChains = filterChains;
    }
    //注:直接从doFilter看
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
    throws IOException, ServletException {
        boolean clearContext = request.getAttribute(FILTER_APPLIED) == null;
        if (clearContext) {
            try {
                request.setAttribute(FILTER_APPLIED, Boolean.TRUE);
                this.doFilterInternal(request, response, chain);
            } finally {
                SecurityContextHolder.clearContext();
                request.removeAttribute(FILTER_APPLIED);
            }
        } else {
            //第一步:具体操作调用下面的doFilterInternal方法了
            this.doFilterInternal(request, response, chain);
        }
    }
    private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain
                                  chain) throws IOException, ServletException {
        FirewalledRequest fwRequest =
        this.firewall.getFirewalledRequest((HttpServletRequest)request);
        HttpServletResponse fwResponse =
        this.firewall.getFirewalledResponse((HttpServletResponse)response);
        //第二步:封装要执行的过滤器链,那么多过滤器就在这里被封装进去了!
        List<Filter> filters = this.getFilters((HttpServletRequest)fwRequest);
        if (filters != null && filters.size() != 0) {
            FilterChainProxy.VirtualFilterChain vfc = new
            FilterChainProxy.VirtualFilterChain(fwRequest, chain, filters);
            //第四步:加载过滤器链
            vfc.doFilter(fwRequest, fwResponse);
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug(UrlUtils.buildRequestUrl(fwRequest) 
                             + (filters == null ? " has no matching filters" : " has an empty filter list"));
            }
            fwRequest.reset();
            chain.doFilter(fwRequest, fwResponse);
        }
    }
    private List<Filter> getFilters(HttpServletRequest request) {
        Iterator var2 = this.filterChains.iterator();
        //第三步:封装过滤器链到SecurityFilterChain中!
        SecurityFilterChain chain;
        do {
            if (!var2.hasNext()) {
                return null;
            }
                chain = (SecurityFilterChain)var2.next();
    } while(!chain.matches(request));
    return chain.getFilters();
  }
}

第二步debug结果如下图所示,惊不惊喜?十五个过滤器都在这里了!

再看第三步,怀疑这么久!原来这些过滤器还真是都被封装进SecurityFilterChain中了。

相关文章
|
存储 NoSQL 关系型数据库
InfluxDB 通识篇
InfluxDB 通识篇
2675 0
|
5月前
|
JSON 前端开发 安全
用自定义注解 + 拦截器实现登录鉴权
通过自定义注解 `@Login` 结合 Spring 拦截器,实现声明式登录校验。无需重复编码,自动拦截未登录请求,提升代码可维护性与安全性,适用于前后端分离架构的权限控制实践。
|
5月前
|
安全 Java API
添加 Swagger2 的 Maven 依赖
本文介绍如何在Spring Boot项目中集成Swagger2(2.2.2版本),通过添加Maven依赖、配置SwaggerConfig类,实现在线API文档生成功能,并提供访问路径与生产环境安全禁用建议。
|
5月前
|
缓存 安全 数据挖掘
数据库设计三范式:从理论到实战
本文深入浅出讲解数据库三范式(1NF、2NF、3NF),通过真实案例解析各范式的核心要求与常见误区,强调“范式是工具而非教条”,帮助开发者在规范性与性能间找到平衡,构建合理、易维护的数据模型。
|
5月前
|
JSON 前端开发 Java
Spring Boot 中的 @RequestMapping 与快捷映射注解
`@RequestMapping` 是 Spring MVC 中用于映射 HTTP 请求路径与处理方法的核心注解,可标注在类或方法上。类上使用定义公共前缀,方法上指定具体路径和请求方式。常用属性包括 `value`(路径)、`method`(请求类型)、`produces`(响应类型)。Spring 还提供了 `@GetMapping`、`@PostMapping` 等快捷注解,语义更清晰,推荐优先使用。
|
5月前
|
缓存 安全 前端开发
Thymeleaf:让前后端协作更顺畅的现代模板引擎
Thymeleaf 是 Spring Boot 推荐的模板引擎,支持“自然模板”,HTML 既可静态预览,又能动态渲染。前后端分离开发更高效,语法简洁,集成简单,是服务端渲染的理想选择。
|
5月前
|
NoSQL Shell Linux
Windows 系统下的 MongoDB 单机部署
本文详细介绍 MongoDB 在 Windows 和 Linux 系统中的单机部署方法,涵盖下载安装、目录配置、服务启停、Shell 与 Compass 连接等步骤,助你快速搭建开发与生产环境。
|
5月前
|
Java Spring
Spring Boot 中的 @RequestParam:获取查询参数与表单数据
`@RequestParam` 用于提取 HTTP 请求中的查询参数或表单数据,支持设置参数名、是否必填及默认值。适用于 `?key=value` 形式或 POST 表单,字段多时推荐封装为实体类自动绑定,与 `@PathVariable` 按路径取值不同,用途明确,是处理 Web 请求的常用方式。
|
5月前
|
Java API Spring
Spring Boot 中的 @PathVariable:获取 RESTful 路径参数
在Spring Boot中,`@PathVariable`用于提取RESTful API URL中的动态参数。支持单个或多个路径变量,参数名一致时可省略value属性,不一致时需显式绑定,是构建清晰、语义化接口的关键注解之一。
|
5月前
|
IDE Java 开发工具
Spring Boot 中多个配置信息的优雅管理
本课详解Spring Boot中如何用@ConfigurationProperties优雅管理多配置项,通过配置类集中绑定YAML属性,提升代码可读性与维护性,适用于微服务、数据库等场景,推荐为进阶开发必备技能。

热门文章

最新文章