项目部署后,观察日志发现有很多这样的内容:
Invalid character found in method name [xxx]. HTTP method names must be tokens
撇开网上很多说的http->https, 改header缓冲区大小,检查请求路径是否正确。我可以肯定,部署的这个项目完全没有上述问题!
以前也遇到过这个问题,当时没处理掉也就记录了下过程。SpringBoot项目出现HTTP method names must be tokens…
复现问题
在后端服务中,加个简单接口/api/hello
正常请求: curl -X GET localhost:8000/api/hello
异常请求: curl -X GET[ab+3 localhost:8000/api/hello
观察到了相似的日志。说明这个问题的出现,其实就和日志描述的内容一样,是请求方法不标准,有乱七八糟的字符混进去了。(另外,这类请求基本都是来自互联网上,可能是爬虫程序扫描,也可能是一些人的恶意请求。但这类日志,其实对程序而言是没有影响的,无非是看着心烦。但是真的很烦!!!)
排查
首先,根据日志内容,找到了定义这项异常的配置,LocalStrings.properties
,它位于Spring Boot内置的Tomcat中。
之后按这条配置项名称iib.invalidmethod
查找,在org.apache.coyote.http11.Http11InputBuffer
类的 parseRequestLine
方法中抛出了异常。
看到这里,就想到用过滤器/拦截器,在抛出这个异常之前先给他过滤掉。但是行不通,请求是先去的tomcat这个方法进行处理,然后才到的过滤器。
解决
或许其实也不算解决吧…
顺着上面的思路,就想给它尽早过滤了
使用Nginx反向代理Web服务,让请求在到达服务之前,先由Nginx过滤掉这些奇怪的请求方法。
示例
后端服务端口: 8010
Nginx配置
server {
listen 8020;
location / {
# 反向代理到后端服务
proxy_pass http://192.168.1.117:8010; # 后端服务地址
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 仅允许 GET|POST|PUT|DELETE 请求
if ($request_method !~ ^(GET|POST|PUT|DELETE)$) {
return 400;
}
}
}
测试
请求Nginx反向代理后的端口地址
异常请求: curl -X GET[ab+3 localhost:8020/api/hello
请求被Nginx拒绝了,后端服务里那条烦人的异常日志终于没了!