Tomcat 内置过滤器详解
Tomcat 提供了多种内置过滤器(Filter),用于处理跨域请求、安全防护、编码设置等常见场景。这些过滤器通过配置 web.xml
即可生效,无需手动编码实现。本文将详细介绍常用的 Tomcat 内置过滤器及其配置方式。
CorsFilter:跨域资源共享过滤器
org.apache.catalina.filters.CorsFilter
实现了 W3C 跨域资源共享(CORS)规范,用于解决前端跨域请求被浏览器拦截的问题。其核心功能是在 HTTP 响应中添加 Access-Control-*
系列头信息,允许指定域的请求访问资源。
配置示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| <filter> <filter-name>CorsFilter</filter-name> <filter-class>org.apache.catalina.filters.CorsFilter</filter-class> <init-param> <param-name>cors.allowed.origins</param-name> <param-value>https://example.com,http://localhost:3000</param-value> </init-param> <init-param> <param-name>cors.allowed.methods</param-name> <param-value>GET,POST,PUT,DELETE,OPTIONS</param-value> </init-param> <init-param> <param-name>cors.allowed.headers</param-name> <param-value>Content-Type,Authorization,X-Requested-With</param-value> </init-param> <init-param> <param-name>cors.exposed.headers</param-name> <param-value>Access-Control-Allow-Origin</param-value> </init-param> <init-param> <param-name>cors.support.credentials</param-name> <param-value>true</param-value> </init-param> <init-param> <param-name>cors.preflight.maxage</param-name> <param-value>3600</param-value> </init-param> </filter> <filter-mapping> <filter-name>CorsFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
关键参数说明
cors.allowed.origins
:限制允许跨域的源(避免滥用 *
,生产环境建议指定具体域名)。
cors.support.credentials
:设为 true
时,cors.allowed.origins
不能为 *
,需指定具体域名。
cors.preflight.maxage
:减少预检请求次数,提升性能。
CsrfPreventionFilter:跨站请求伪造防护
CsrfPreventionFilter
用于防御跨站请求伪造(CSRF)攻击,原理是:
- 生成随机令牌(CSRF Token)并存储在会话中。
- 要求客户端请求中携带该令牌(通常通过 URL 参数或表单字段)。
- 验证请求中的令牌与会话中的令牌是否一致,不一致则拒绝请求。
配置示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <filter> <filter-name>CsrfPreventionFilter</filter-name> <filter-class>org.apache.catalina.filters.CsrfPreventionFilter</filter-class> <init-param> <param-name>excludedPaths</param-name> <param-value>/static/*,/api/public/*</param-value> </init-param> <init-param> <param-name>csrfParameterName</param-name> <param-value>csrfToken</param-value> </init-param> <init-param> <param-name>csrfAttributeName</param-name> <param-value>sessionCsrfToken</param-value> </init-param> <init-param> <param-name>tokenLength</param-name> <param-value>64</param-value> </init-param> </filter> <filter-mapping> <filter-name>CsrfPreventionFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
使用方式
客户端请求需携带令牌,例如:
1 2 3 4 5 6 7 8 9 10 11
| <form action="/submit" method="post"> <input type="hidden" name="csrfToken" value="${sessionScope.sessionCsrfToken}"> </form>
$.ajax({ url: "/api/data", data: { csrfToken: "${sessionScope.sessionCsrfToken}" } });
|
ExpiresFilter:缓存控制过滤器
ExpiresFilter
用于设置响应头中的 Expires
和 Cache-Control: max-age
,控制客户端(浏览器)缓存静态资源(如 JS、CSS、图片),减少重复请求,提升性能。
配置示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
| <filter> <filter-name>ExpiresFilter</filter-name> <filter-class>org.apache.catalina.filters.ExpiresFilter</filter-class> <init-param> <param-name>ExpiresByType text/css</param-name> <param-value>access plus 1 days</param-value> </init-param> <init-param> <param-name>ExpiresByType application/javascript</param-name> <param-value>access plus 1 days</param-value> </init-param> <init-param> <param-name>ExpiresByType image/jpeg</param-name> <param-value>access plus 7 days</param-value> </init-param> <init-param> <param-name>ExpiresByType image/png</param-name> <param-value>access plus 7 days</param-value> </init-param> <init-param> <param-name>DefaultExpires</param-name> <param-value>access plus 1 hours</param-value> </init-param> </filter> <filter-mapping> <filter-name>ExpiresFilter</filter-name> <url-pattern>*.css</url-pattern> <url-pattern>*.js</url-pattern> <url-pattern>*.jpg</url-pattern> <url-pattern>*.png</url-pattern> </filter-mapping>
|
时间格式说明
access plus 1 days
:从访问时间起,缓存 1 天。
modification plus 1 weeks
:从资源修改时间起,缓存 1 周。
SetCharacterEncodingFilter:编码设置过滤器
SetCharacterEncodingFilter
用于统一设置请求和响应的字符编码,解决中文乱码问题。其原理是调用 request.setCharacterEncoding()
和 response.setCharacterEncoding()
。
配置示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| <filter> <filter-name>SetCharacterEncodingFilter</filter-name> <filter-class>org.apache.catalina.filters.SetCharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceResponseEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <filter-mapping> <filter-name>SetCharacterEncodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
注意事项
- 需配置在所有过滤器的最前面,避免其他过滤器提前读取请求参数导致编码设置失效。
- 对于 POST 请求,需在读取参数前设置编码;GET 请求的编码需配合 Connector 的
URIEncoding="UTF-8"
配置。
RemoteIpFilter:获取真实客户端 IP
当 Tomcat 部署在反向代理(如 Nginx)之后,直接通过 request.getRemoteAddr()
只能获取代理服务器的 IP。RemoteIpFilter
可解析代理添加的 X-Forwarded-For
或 X-Real-IP
头,获取真实客户端 IP。
配置示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <filter> <filter-name>RemoteIpFilter</filter-name> <filter-class>org.apache.catalina.filters.RemoteIpFilter</filter-class> <init-param> <param-name>remoteIpHeader</param-name> <param-value>X-Forwarded-For</param-value> </init-param> <init-param> <param-name>protocolHeader</param-name> <param-value>X-Forwarded-Proto</param-value> </init-param> <init-param> <param-name>internalProxies</param-name> <param-value>192.168.1.0/24,10.0.0.0/8</param-value> </init-param> </filter> <filter-mapping> <filter-name>RemoteIpFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>
|
效果
配置后,request.getRemoteAddr()
将返回 X-Forwarded-For
中的第一个 IP(真实客户端 IP),request.isSecure()
会根据 X-Forwarded-Proto
判断是否为 HTTPS 协议。
其他实用过滤器
过滤器名称 |
功能说明 |
FailedRequestFilter |
当请求参数解析失败(如格式错误)时拒绝请求,需配合 SetCharacterEncodingFilter 使用。 |
RemoteAddrFilter |
根据客户端 IP 地址过滤请求(如只允许特定 IP 访问)。 |
RemoteHostFilter |
根据客户端主机名过滤请求(如只允许特定域名访问)。 |
v1.3.10