0%

tomcat之过滤器

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>
<!-- 允许的 HTTP 方法 -->
<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>
<!-- 是否支持带凭据的请求(如 Cookie、Authorization) -->
<init-param>
<param-name>cors.support.credentials</param-name>
<param-value>true</param-value>
</init-param>
<!-- 预检请求(OPTIONS)结果的缓存时间(秒) -->
<init-param>
<param-name>cors.preflight.maxage</param-name>
<param-value>3600</param-value> <!-- 1小时 -->
</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)攻击,原理是:

  1. 生成随机令牌(CSRF Token)并存储在会话中。
  2. 要求客户端请求中携带该令牌(通常通过 URL 参数或表单字段)。
  3. 验证请求中的令牌与会话中的令牌是否一致,不一致则拒绝请求。

配置示例

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>
<!-- 排除不需要验证的 URL 模式(如静态资源) -->
<init-param>
<param-name>excludedPaths</param-name>
<param-value>/static/*,/api/public/*</param-value>
</init-param>
<!-- 令牌参数名(默认 _csrf) -->
<init-param>
<param-name>csrfParameterName</param-name>
<param-value>csrfToken</param-value>
</init-param>
<!-- 会话中令牌的属性名(默认 csrfToken) -->
<init-param>
<param-name>csrfAttributeName</param-name>
<param-value>sessionCsrfToken</param-value>
</init-param>
<!-- 令牌长度(默认 32 字节) -->
<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 请求 -->
$.ajax({
url: "/api/data",
data: { csrfToken: "${sessionScope.sessionCsrfToken}" }
});

ExpiresFilter:缓存控制过滤器

ExpiresFilter 用于设置响应头中的 ExpiresCache-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>
<!-- 对 CSS、JS 缓存 1 天 -->
<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>
<!-- 对图片缓存 7 天 -->
<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>
<!-- 默认缓存 1 小时 -->
<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>
<!-- 是否强制覆盖响应编码(默认 false) -->
<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-ForX-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>
<!-- 信任的代理服务器 IP 或 CIDR 网段 -->
<init-param>
<param-name>remoteIpHeader</param-name>
<param-value>X-Forwarded-For</param-value> <!-- 代理传递的客户端 IP 头 -->
</init-param>
<init-param>
<param-name>protocolHeader</param-name>
<param-value>X-Forwarded-Proto</param-value> <!-- 代理传递的协议(http/https) -->
</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 根据客户端主机名过滤请求(如只允许特定域名访问)。

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10