You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring请求参数UTF-8支持:如何在CsrfFilter前配置编码过滤器

遇到过类似的问题,Spring Security的CsrfFilter确实会在很多自定义过滤器之前读取请求参数,导致后续的编码设置失效。这里有两个可靠的解决方案,帮你彻底解决UTF-8编码问题:

方案1:在web.xml中配置编码过滤器(推荐)

这是最直接的解决方式,因为web.xml中定义的过滤器会优先于Spring Security的整个过滤器链执行,完全避开CsrfFilter先读取参数的问题。

你不需要自定义过滤器,直接用Spring提供的CharacterEncodingFilter即可,配置如下:

<filter>
    <filter-name>encodingFilter</filter-name>
    <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
    <init-param>
        <param-name>encoding</param-name>
        <param-value>UTF-8</param-value>
    </init-param>
    <init-param>
        <param-name>forceEncoding</param-name>
        <param-value>true</param-value>
    </init-param>
</filter>
<filter-mapping>
    <filter-name>encodingFilter</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>REQUEST</dispatcher>
    <dispatcher>FORWARD</dispatcher>
</filter-mapping>

forceEncoding=true会强制为request和response都设置UTF-8编码,确保后续所有读取参数的操作(包括CsrfFilter)都会使用正确的编码。

方案2:在Spring Security链中正确插入自定义编码过滤器

如果你一定要在Spring Security的过滤器链中处理编码,关键是要准确指定过滤器在CsrfFilter之前执行,同时确保Spring Security的配置完整,避免AuthenticationEntryPoint的异常。

第一步:修正Spring Security配置

不要单独创建新的<http>块,而是把自定义过滤器放在你原来的http配置里,用before="CSRF_FILTER"明确指定位置:

<http auto-config="true" use-expressions="true">
    <intercept-url pattern="/**" access="permitAll" /> <!-- 用permitAll更适合匿名访问场景 -->
    <access-denied-handler ref="myAccessDeniedHandler"/>
    <!-- 关键:在CsrfFilter之前插入编码过滤器 -->
    <custom-filter before="CSRF_FILTER" ref="utf8Filter" />
</http>

<beans:bean id="utf8Filter" class="my.SetRequestEncodingFilter">
    <beans:property name="encoding" value="UTF-8"/>
    <beans:property name="forceEncoding" value="true"/>
</beans:bean>

这里把hasRole('ROLE_ANONYMOUS')改成permitAll更合理,因为它直接表示允许所有用户(包括匿名)访问,避免了角色检查的潜在问题。

第二步:完善自定义过滤器

你的SetRequestEncodingFilter最好继承Spring的CharacterEncodingFilter或者OncePerRequestFilter,确保编码设置只执行一次:

public class SetRequestEncodingFilter extends CharacterEncodingFilter {
    public SetRequestEncodingFilter() {
        super.setEncoding("UTF-8");
        super.setForceEncoding(true);
    }
}

或者自己实现逻辑:

public class SetRequestEncodingFilter extends OncePerRequestFilter {
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        // 仅在首次调用前设置编码
        if (request.getCharacterEncoding() == null) {
            request.setCharacterEncoding("UTF-8");
        }
        response.setCharacterEncoding("UTF-8");
        filterChain.doFilter(request, response);
    }
}

为什么之前的配置报错?

你之前单独创建<http>块添加自定义过滤器,覆盖了原来的完整配置,导致Spring Security无法自动初始化AuthenticationEntryPoint。必须把自定义过滤器放在包含auto-config、intercept-url等完整配置的同一个<http>块里,这样Spring才能正确构建安全链。

内容的提问来源于stack exchange,提问作者user2177118

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:50:39