java.lang.IllegalArgumentException: Invalid character found in the request target.

在Spring Boot应用中,当GET请求的URL中包含方括号[]等特殊字符时,可能会触发java.lang.IllegalArgumentException: Invalid character found in the request target异常。这是因为Tomcat(默认嵌入式容器)对URL的合规性检查遵循了RFC 7230和RFC 3986,而方括号在这些标准中是不允许的。

服务端报错为:

<!doctype html> HTTP Status 400 – Bad Request

HTTP Status 400 – Bad Request

要解决这个问题,有几种方法:

​​修改Tomcat的配置,放宽对URL字符的限制​​(不推荐,因为会降低安全性,而且不符合RFC标准)。
​​在客户端对特殊字符进行编码​​(推荐在客户端解决)。例如,在URL中,方括号[和]应该分别编码为%5B和%5D。
​​在服务端捕获该异常,并返回一个友好的错误信息​​。
​​使用过滤器对请求URL进行过滤,将特殊字符进行替换或编码转换​​(注意:这可能会改变请求的原始意图,且实现复杂)。
这里,我们主要讨论服务端的处理:如何捕获该异常以及如何过滤。

要解决Spring Boot GET接口因URL中包含[]特殊字符导致的java.lang.IllegalArgumentException错误,并提供友好的错误处理,以下是完整的解决方案:

方法一:修改Tomcat配置(允许特殊字符)
​​步骤:​​

配置application.properties:

允许[]在路径和查询参数中出现

server.tomcat.relaxed-path-chars=‘[]’
server.tomcat.relaxed-query-chars=‘[]’
或通过Java配置类:
@Configuration
public class TomcatConfig {

@Bean
public WebServerFactoryCustomizer<TomcatServletWebServerFactory> tomcatCustomizer() {
    return factory -> factory.addConnectorCustomizers(connector -> {
        connector.setProperty("relaxedPathChars", "\"<>[\\]^`{|}");  // 添加需要的特殊字符
        connector.setProperty("relaxedQueryChars", "\"<>[\\]^`{|}");
    });
}

}
​​注意事项:​​

此方法​​降低安全性​​(可能引入HTTP响应拆分攻击)
仅适用于Tomcat服务器
方法二:全局异常处理(捕获并返回友好错误)
​​步骤:​​

创建异常处理类:
@ControllerAdvice
public class GlobalExceptionHandler {

@ExceptionHandler(IllegalArgumentException.class)
public ResponseEntity<Map<String, String>> handleInvalidRequest(IllegalArgumentException ex) {
    if (ex.getMessage() != null && ex.getMessage().contains("Invalid character found")) {
        return ResponseEntity.badRequest().body(Map.of(
            "code", "ILLEGAL_CHARACTER",
            "message", "URL包含非法字符,请移除特殊符号如[]"
        ));
    }
    return ResponseEntity.internalServerError().body(Map.of("error", "服务器内部错误"));
}

}
添加Servlet异常监听器:
@Bean
public ServletWebServerFactory webServerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory();
factory.addErrorPages(new ErrorPage(HttpStatus.BAD_REQUEST, “/error/400”));
return factory;
}

@RestController
@RequestMapping(“/error”)
public class ErrorController implements org.springframework.boot.web.servlet.error.ErrorController {

@GetMapping("/400")
public ResponseEntity<Map<String, String>> handleBadRequest() {
    return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(Map.of(
        "code", "INVALID_REQUEST",
        "message", "请求包含非法字符(如[]),请进行URL编码"
    ));
}

}
方法三:URL编码过滤器(自动转义特殊字符)
​​步骤:​​
创建URL重写过滤器:

@WebFilter(urlPatterns = “/*”)
public class UrlDecodeFilter implements Filter {

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
        throws IOException, ServletException {
    HttpServletRequest httpRequest = (HttpServletRequest) request;
    String requestURI = httpRequest.getRequestURI();
    String queryString = httpRequest.getQueryString();

    try {
        // 尝试直接处理(验证是否有效)
        chain.doFilter(request, response);
    } catch (IllegalArgumentException e) {
        // 发生异常时重编码URL
        String safeURI = URLEncoder.encode(requestURI, StandardCharsets.UTF_8.name())
                        .replaceAll("%2F", "/");  // 保留路径分隔符
        
        String safeQuery = (queryString != null) ? 
                        "?" + URLEncoder.encode(queryString, StandardCharsets.UTF_8) : "";
        
        String newUrl = safeURI + safeQuery;
        ((HttpServletResponse) response).sendRedirect(newUrl);
    }
}

}
推荐方案:结合使用
​​优先使用方法二​​(全局异常处理),因为最安全且符合标准
如果必须接受特殊字符:
内部系统:使用方法一(Tomcat配置)
对外系统:要求客户端进行URL编码(前端将[编码为%5B,]编码为%5D)
添加日志监控非法请求:
@ControllerAdvice
public class LoggingAdvice {
@ExceptionHandler(IllegalArgumentException.class)
public void logInvalidRequest(IllegalArgumentException ex, HttpServletRequest request) {
if (ex.getMessage().contains(“Invalid character found”)) {
logger.warn(“非法URL请求: {}?{}”,
request.getRequestURI(),
request.getQueryString());
}
}
}
客户端处理建议
// 前端发送请求前编码特殊字符
const encodeSpecialChars = (url) => {
return url.replace(/ / g , ′ /g, '%5B').replace(/ /g,/g, ‘%5D’);
};

fetch(encodeSpecialChars(‘/api/data?filter=array[1]’))
​​最终选择​​:

​​安全性优先​​:使用方法二返回HTTP 400错误,强制客户端合规编码
​​兼容性优先​​:内部系统可开方法一(但需评估安全风险)
​​禁止修改URL的场景​​:用方法三(注意重定向可能改变语义)

选择
方法二:配置Tomcat的Connector(不推荐,但有时需要)
在Spring Boot中,我们可以通过修改application.properties或application.yml来配置Tomcat,允许特定的非法字符。

并在代码中对参数进行正则校验
补充全局异常处理

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐