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

如何让Spring Boot控制器端点在接收含无效字符的请求时返回400 Bad Request而非500 Internal Server Error?

当然可以搞定这个问题!当URL里包含像%2500这类无效字符时,Spring Boot默认会把容器(比如Tomcat)抛出的异常转换成500内部错误,但我们可以通过几种方式调整,让它返回更符合语义的400 Bad Request。下面给你两种实用的方案:

方案一:自定义全局异常处理器

这种方法是捕获容器层抛出的非法URL异常,直接返回400状态码。以Tomcat为例,当请求URL包含无效字符时,它会抛出IllegalArgumentException(或者Tomcat特定的Http11InputBuffer.ParseException),我们可以通过全局异常处理器拦截这类异常:

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;

@ControllerAdvice
public class GlobalUrlExceptionHandler {

    // 处理Tomcat抛出的URL非法字符异常
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<String> handleInvalidUrlArgument(IllegalArgumentException ex) {
        // 判断异常信息是否匹配URL非法字符的场景
        if (ex.getMessage().contains("Invalid character found in the request target")) {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                    .body("请求URL包含无效字符,请检查后重试");
        }
        // 其他参数异常按原有逻辑处理
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                .body(ex.getMessage());
    }

    // 捕获Tomcat特定的解析异常(部分Tomcat版本会抛出这个)
    @ExceptionHandler(org.apache.coyote.http11.Http11InputBuffer.ParseException.class)
    public ResponseEntity<String> handleTomcatUrlParseException(org.apache.coyote.http11.Http11InputBuffer.ParseException ex) {
        return ResponseEntity.status(HttpStatus.BAD_REQUEST)
                .body("请求格式无效,URL包含非法字符");
    }
}

这个方案的好处是不用修改容器配置,直接利用Spring的全局异常处理机制,覆盖默认的500返回逻辑。

方案二:自定义过滤器提前拦截

如果想在请求到达控制器之前就拦截掉非法URL,可以写一个自定义过滤器,提前检查URL中的无效字符:

import jakarta.servlet.Filter;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.regex.Pattern;

@Component
public class UrlValidationFilter implements Filter {

    // 定义需要拦截的无效字符正则(这里匹配空字节的URL编码形式)
    private static final Pattern INVALID_URL_CHAR_PATTERN = Pattern.compile("%00|%2500", Pattern.CASE_INSENSITIVE);

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        HttpServletResponse httpResponse = (HttpServletResponse) response;

        String requestUri = httpRequest.getRequestURI();
        String queryString = httpRequest.getQueryString();

        // 检查请求路径和查询参数中是否存在无效字符
        boolean hasInvalidChar = INVALID_URL_CHAR_PATTERN.matcher(requestUri).find();
        if (!hasInvalidChar && queryString != null) {
            hasInvalidChar = INVALID_URL_CHAR_PATTERN.matcher(queryString).find();
        }

        if (hasInvalidChar) {
            httpResponse.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            httpResponse.getWriter().write("请求URL包含无效字符,请检查后重试");
            return;
        }

        // 没有问题,继续执行后续流程
        chain.doFilter(request, response);
    }
}

这个方案更灵活,你可以根据需求扩展正则表达式,拦截更多类型的非法字符。

注意事项

  • 如果你用的是Tomcat以外的容器(比如Jetty、Undertow),抛出的异常类型会不同,需要调整异常处理器捕获的异常类。比如Jetty会抛出org.eclipse.jetty.http.BadMessageException,Undertow则是io.undertow.server.handlers.form.FormParserException之类的异常。
  • 不要随便使用server.tomcat.relaxed-path-chars或server.tomcat.relaxed-query-chars配置,这些是用来允许某些特殊字符,而不是拒绝,可能带来安全风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 14:27:32