从 Filter / Interceptor 到 HTTPS
一次真正理解 Java Web 请求与安全的完整旅程
我写这篇文章的起点,并不是想系统学习 Java Web,而是被一个看似简单的问题卡住了:
过滤器(Filter)和拦截器(Interceptor)到底有什么区别?
结果我一路追着这个问题,慢慢把 请求是怎么来的、Session 是什么、Cookie 在哪、HTTP 为什么不安全 全部串了起来。
如果你也和我一样,对这些概念"会用但总觉得不踏实",那这篇文章可能正好对你有用。
一、从一个最经典的问题开始:Filter 和 Interceptor 有什么区别?
一开始我很困惑:
- Filter 能拦请求
- Interceptor 也能拦请求
- 在 Spring Boot 里都能用 Java 配置
那它们到底差在哪?
后来我才意识到,我的问题不在"API",而在请求走到哪一层了。
一个直观结论是:
- Filter :工作在 Servlet 容器层(Tomcat)
- Interceptor :工作在 Spring MVC 层
也就是说:
请求是 先到 Filter ,再到 Interceptor,最后才到 Controller。
Filter 不知道你访问的是哪个 Controller;
Interceptor 知道你调用的是哪个方法。
这个区别,后面会贯穿全文。
二、Tomcat 明明管理 Filter、Session、Cookie,为什么我能在 Spring Boot 里配置?
这一步我直接懵了。
既然:
- Filter 是 Tomcat 管的
- Session 是 Tomcat 管的
- Cookie 也是 Tomcat 管的
那我在 Spring Boot 里写的这些配置算什么?
后来我终于理解了一个非常重要的分界线:
Tomcat 负责"运行期行为",
Spring Boot 负责"启动期装配"。
Spring Boot 并没有"接管" Tomcat,它只是:
- 在启动时
- 用 Java 代码
- 把 Filter / Session 配置
- 注册给 Tomcat
真正请求来的时候,执行逻辑仍然在 Tomcat。
Spring Boot 只是一个高级装配工。
三、Servlet、Servlet 容器、Web 容器、Tomcat 到底谁是谁?
我以前最大的混乱来源就在这。
后来我用一句话把它们分清了:
- Servlet:一套"处理 HTTP 请求的规范接口"
- Servlet 容器 / Web 容器:运行 Servlet 的环境
- Tomcat:最常见的 Servlet 容器
- Spring Boot:帮你把 Tomcat + Spring 一起启动的框架
Spring MVC 的核心其实只有一个 Servlet:
DispatcherServlet
所有 Controller,本质上都在它后面。
四、一次完整的用户请求,到底经历了什么?
这一步是我真正"通透"的开始。
从浏览器敲回车开始:
- 浏览器做 DNS 解析
- 建立 TCP 连接(三次握手)
- 构造 HTTP 请求
- 通过 TCP 把字节发出去
到服务器之后:
- 操作系统接收 TCP 数据
- Tomcat 解析 HTTP
- 进入 Filter 链
- 进入 DispatcherServlet
- 执行 Interceptor
- 调用 Controller
- 原路返回
这一条链路一旦在脑子里跑通,后面的所有概念都会自动归位。
五、HTTP 和 TCP 明明是不同层,那 HTTP 是怎么被"发出去"的?
我曾经卡在这里很久。
后来一句话把我点醒了:
HTTP 不负责传输,它只定义"数据长什么样";
真正负责传输的是 TCP。
HTTP 请求在真正发送前,会被序列化成 字节流 。
TCP 只负责把这堆字节,可靠地送到对方。
TCP 完全不知道什么是:
- Header
- Cookie
- Session
它只管字节。
六、Cookie 和 Session 到底是谁的?第一次请求为什么没有?
这是另一个非常大的误区。
第一次请求时:
- 浏览器 没有 Cookie
- 服务器 没有 Session
这是完全正常的。
只有当服务器需要记住你时,它才会:
-
创建 Session(服务器内存)
-
生成一个 SessionId
-
通过响应头发给浏览器:
Set-Cookie: JSESSIONID=xxx
之后浏览器才会在后续请求中自动带上这个 Cookie。
七、什么叫"Session 是按需创建的"?
我以前以为:
没 Session → 访问不了
后来才发现,这是完全错误的理解。
绝大多数请求,根本不需要 Session。
Session 只在你代码中主动使用它的时候才会创建,比如:
java
request.getSession().setAttribute(...)
而是否允许访问,永远是业务逻辑决定的,不是 Session 本身。
八、为什么要在 Session 里存 user?
这是我最大的"顿悟点"。
我以前以为:
session.setAttribute("user", user)是把 user 发给前端
这是错的。
user 永远只存在服务器内存里。
真实发生的是:
-
服务器内存中:
sessionId -> { user } -
前端只拿到一个 sessionId
-
每次请求只带这个 id
-
服务器用 id 找回自己的数据
SessionId 就像一把钥匙,而不是数据本身。
九、那 SessionId 会不会被偷?
这是一个非常合理、而且非常重要的担忧。
答案是:有风险,但并不"随便就会被偷"。
前提是:
- HTTPS
- Cookie 设置 HttpOnly / Secure
- 登录后重新生成 SessionId
在这些条件下,Session 是一个成熟且安全的方案。
十、公共 WiFi 抓包到底能抓到什么?
这一步,我以前是被"吓大的"。
现实情况是:
- HTTPS 下,抓不到内容
- 只能看到你在"上网"
- 看不到账号、密码、Cookie
真正危险的是:
- HTTP
- 证书被忽略
- 中间人攻击
十一、为什么"直接用 IP 访问"的服务器更危险?
这里我终于把最后一块拼图拼上了。
问题不在 IP 本身,而在于:
HTTPS 的安全性,严重依赖"域名 + 证书校验"。
用 IP 访问时:
- 证书几乎必然校验失败
- 很多人会点"继续访问"
- TLS 身份校验失效
- 中间人攻击成立
这才是"纯 IP 服务危险"的真正原因。
十二、回到最初:我现在对 Web 安全的整体理解
我现在脑子里非常清楚:
- HTTP 天生不安全
- HTTPS 解决的不只是"加密"
- 更重要的是 "你连的是不是对方"
- Session 是服务器状态
- Cookie 只是钥匙
- 安全从来不是"框架自动搞定的"
结语:从"会用"到"理解为什么"
这一路下来,我最大的收获不是记住了多少 API,而是终于搞清楚:
这些设计不是随意的,
而是对真实问题的长期工程解法。
如果你也曾对这些问题一知半解,希望这篇文章能帮你少走一些弯路。