本节摘要:Spring Security 的全部防线安装在一条特殊的过滤器链上,请求在抵达分发器之前先要过这一关。本节讲这条链在旅程中的位置与内部分工,配置一套"公开读、登录写"的最小规则,并跟踪一个未认证请求的完整遭遇,直到它被礼貌地挡回。
第 2 章说过,过滤器先于所有 Servlet。Spring Security 借用这个位置,注册了一条自己的过滤链,内部又排布了十几个各司其职的安全过滤器。不必背全名单,抓两级即可:第一级决定"这个请求要不要过安检"(按路径匹配放行或进入检查),第二级完成"安检本身"(认证过滤器验证凭证、授权过滤器核对权限、异常过滤器兜底处理)。请求在链上任何一环被拒,都不会再前进——这与 2.1 节"不交棒即终止"是同一个原理,安全框架只是把它用到了极致。
一套常见的规则:读接口放行,写接口要登录,管理接口要角色:
@Configuration @EnableWebSecurity public class SecurityConfig { @Bean SecurityFilterChain chain(HttpSecurity http) throws Exception { http.csrf(csrf -> csrf.disable()) // 接口服务通常关掉跨站防护 .authorizeHttpRequests(auth -> auth .requestMatchers("/api/public/**").permitAll() .requestMatchers(HttpMethod.POST, "/api/**").authenticated() .requestMatchers("/api/admin/**").hasRole("ADMIN") .anyRequest().authenticated()) .httpBasic(Customizer.withDefaults()); // 演示用基础认证 return http.build(); } }
规则的匹配顺序是从上到下先中先用,anyRequest 兜底放最后。顺序颠倒(把宽规则写在窄规则前面)是新手配置里最常见的漏洞——宽规则先命中,窄规则永远轮不上。

不带头凭证直接提交写接口,旅程是这样断掉的:请求穿过普通过滤器进入安全链;第一级分拣判定该路径需要认证;认证过滤器在请求上下文里找不到身份,触发未认证事件;异常过滤器接手,调用未认证处理器——浏览器场景重定向到登录页,接口场景返回 401。全程请求没有碰到分发器,更没有到控制器。 这解释了一个排查现象:控制器断点不命中、日志也没有业务痕迹时,先怀疑是被安全链拦下,把安全日志级别调到调试即可看到链上的裁决过程:
logging: level: org.springframework.security: TRACE
⚠️ 跨域预检请求不带凭证,会被认证检查拦下造成"接口偶尔通偶尔不通"的假象。预检路径必须放在放行名单里,这是前后端联调阶段的高频故障。
背景:联调时同事反馈"带登录态请求管理接口仍然 403",需要完整走一遍排查。操作:第一步,打开安全链的跟踪级日志(上文那段配置)。第二步,重放请求,日志里出现链上每个过滤器的裁决轨迹。第三步,对号入座找断点:日志显示认证过滤器已通过(身份在场),断点落在授权过滤器;再看配置——管理接口声明了管理员角色,而当前用户只有普通角色。结果:这是预期行为而非故障,403 与 401 的区别由此明确——401 是"没验明正身",403 是"验明了但不够格"。
解读:这次排查顺带验证了链上两级分工:认证在前授权在后,日志顺序永远是认证先出现。变式一:把管理规则移到公开规则之前再重放,行为不变——说明先中先用的前提是规则都能命中,宽窄顺序的坑在"宽规则吞掉窄规则"时才显形。变式二:临时给用户加上管理员角色再请求,403 变 200,闭环确认。把这组三变式做成团队的排错剧本,安全类工单的定位时间能从半小时压到五分钟。
第一,通读规则顺序,确认"从窄到宽"——带角色、带方法的精确规则在前,宽泛的兜底在后,评审时只看顺序就能拦下一半漏洞。第二,清点放行名单里的每一项,逐条问"它为什么可以公开";名单只增不减是常态事故,每季度删一次没人认领的放行项。第三,确认跨域、预检、健康检查三类特殊路径各有明确安排,它们是"偶尔不通"类工单的三大常客。安全配置没有银弹,把动作固化成清单,比依赖个人警觉可靠。另外提醒:演示项目里关闭跨站防护的写法切勿原样搬进面向浏览器的生产应用,那道防护拦的正是浏览器环境下的伪造请求。
回收三问:未认证与权限不足分别返回什么状态码,对应链上哪两环;规则顺序写反会产生什么后果;联调时"接口偶尔通偶尔不通"第一怀疑对象是什么。三问对应三类真实工单,值得抄进团队排错手册。
再从攻击者视角补一句:安全链的裁决全部发生在服务端,前端隐藏按钮、校验参数都只是体验层动作,绕过它们直接发包的成本低到可以忽略。本节的靶场实验之所以先裸奔再加防护,就是要让这个认知从口号变成亲眼所见。安全设计的第一性原则由此而来:一切校验以服务端为准,前端的任何逻辑都可能不存在。
还有一条联调期经验值得记下:跨域问题排障时,先分清"预检失败"与"业务请求失败"——浏览器控制台里看请求方法,预检是探测性方法。两者混淆时,团队常在业务代码里白找半天,而真正的修复点只在放行名单里加一行,一分钟的事。