java

关注公众号 jb51net

关闭
首页 > 软件编程 > java > Spring Security 拦截机制

一个开发者对 Spring Security 拦截机制的深度追问(最新推荐)

作者:旷野说

作者通过一次调试经历,深入探讨了SpringSecurity的拦截机制,揭示了Filter与AOP在安全控制中的不同职,责,并分享了调试和理解框架的技巧,感兴趣的朋友跟随小编一起看看吧

🚨“为什么我的接口突然 403 了?”

🧩 一、那个让人抓狂的下午

上周三下午,我正和前端同事联调一个新功能。

他调用 /api/v1/orders/create 接口,返回:

{
  "status": 403,
  "message": "Access Denied"
}

“你是不是没给我开权限?”他问。

我皱眉:“不可能。我用的是管理员账号,Token 是刚登录拿的,而且本地跑得好好的。”

我打开 Postman 重试:

更诡异的是:断点根本没进 Controller
我甚至在 Controller 第一行打了日志,结果日志没输出。

“请求……根本没进来?”我喃喃自语。

那一刻,我意识到:

我的代码不是被业务逻辑拒绝的,而是被某一层“看不见的安全机制”提前拦截了。

而我对这层机制,几乎一无所知。

❓ 二、带着问题,向底层进发

我开始追问自己:

这些问题,像一张密网,把我困在“配置能跑,但原理不清”的模糊地带。

于是,我决定:不再把 Spring Security 当成黑盒。我要搞清楚,从请求进来到被拦截,究竟发生了什么

🔍 三、真相的起点:Servlet Filter

经过翻源码、读文档、画流程图,我终于找到了答案的起点——

Spring Security 的安全拦截,根本不在 Spring 的 Bean 层,而是在更底层:Servlet 容器层。

换句话说:
你的请求,甚至还没到达 DispatcherServlet,就已经被一连串 Filter 检查过了。

而这一切,都基于 Java Web 最基础的机制:Servlet Filter

📦 四、什么是 Servlet Filter?

Filter 是 Java EE(现 Jakarta EE)标准的一部分,由 Tomcat、Jetty 等容器管理。

它能在 请求到达目标资源(如 Controller)前,或 响应返回前,对请求/响应进行拦截和处理。

核心方法就一个:

void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)

⚠️ Filter 是链式执行的,顺序至关重要。

🧱 五、Spring Security 的核心:FilterChainProxy

Spring Security 并没有把十几个安全 Filter 直接注册到 Tomcat,而是把它们全部封装在一个特殊的 Filter 里FilterChainProxy

它像一个“安全中枢”,内部维护了一整条过滤器链:

graph LR
    A[HTTP Request] --> B[FilterChainProxy]
    B --> C[SecurityContextPersistenceFilter]
    B --> D[JwtAuthenticationFilter]     // 我们自定义的
    B --> E[ExceptionTranslationFilter]
    B --> F[FilterSecurityInterceptor]   // 最终权限校验!
    F --> G[DispatcherServlet → Controller]

💡 关键发现
我的 /orders/create 接口之所以 403,就是因为 FilterSecurityInterceptor 拦截了它——
而这时,我的 Controller 根本还没机会执行!

🔑 六、为什么/profile能过,/orders/create不行?

我检查了安全配置:

.authorizeHttpRequests(authz -> authz
    .requestMatchers("/login").permitAll()
    .anyRequest().authenticated()
)

看起来没问题啊?所有接口只要登录就能访问。

但后来我发现:我在 Service 层还加了 @PreAuthorize

@Service
public class OrderService {
    @PreAuthorize("hasRole('ADMIN')")
    public Order createOrder(OrderDto dto) { ... }
}

/profile 没有方法级注解。

真相大白

但为什么没看到异常堆栈?

因为 ExceptionTranslationFilterAccessDeniedException 捕获后,静默转成了 403 响应——这正是 Spring Security 的“优雅”设计,也是调试的难点。

⚖️ 七、Filter vs AOP:职责分明

现在我终于理清了两者的分工:

机制作用层级典型用途是否依赖 Spring
Servlet FilterHTTP 请求层JWT 认证、CORS、日志、URL 权限❌ 不依赖(容器级)
Spring AOP方法调用层@PreAuthorize、事务、缓存✅ 依赖 Spring Bean

Spring Security = Filter(Web 安全) + AOP(方法安全)

🧠 八、终极口诀:14 个字,牢牢记住

“Filter 拦请求,AOP 拦方法”
“Web 层用 Filter,服务层用 AOP”

✅ 九、总结:从“能用”到“懂用”

这次 403 异常,像一记警钟,敲醒了我:

不要把框架当魔法。
只有理解底层机制,才能在问题发生时,一眼看穿本质。

现在,当我再看到 Spring Security 的配置:

.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class)
.sessionManagement().sessionCreationPolicy(STATELESS)
.authorizeHttpRequests(...).authenticated()

我不再觉得它只是“模板代码”,而是一个精密的安全流水线——每一步都有其不可替代的作用。

而那个下午的困惑,也成了我深入理解 Web 安全架构的起点。

📚 延伸建议

愿你下次再遇 403,不再慌张,而是微微一笑:

“哦,我知道你在哪拦我了。”

到此这篇关于一个开发者对 Spring Security 拦截机制的深度追问的文章就介绍到这了,更多相关Spring Security 拦截机制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文