记录一次Bug的查找
目录赶时间的小伙伴直接看结论即可。
结论
-
JMtmer的
\r
需要进行编码 编码为
-
POST请求,最好一定要带上
Content-Length
,Content-Type
-
SP 和 CR 不是一个东西 CR是回车,SP是空格
-
换行: Windows下为CRLF,Linux下为LF
问题:
Linnx下的JMeter 的发送SSL--RSA的POST请求,无法发送,返回码为 400, 提示 请求头异常,服务端不认识请求头。
环境简介:
Centos7 安装的 JMeter 5.2.1版本。
JMtmer实现SSL请求方式为:JMtmer调用Jar包,Jar包调用.so库实现 SSL。 而此时request请求是作为一个参数传入给Jar包的。
解决思路:
1. 查看请求头
检查了发送的请求头,发现代码里面写了 Content-Type:text
的,而服务端需要使用application/json
格式,于是我曾尝试加2个Content-Type
,但是没有成功。这也引出来一个问题,同一个请求头,重复的字段,到底哪个生效?
2.使用Win下的JMeter测试
使用win下JMtmer 自带的SSL 进行测试---使用方法为:选项--SSL管理器--选择CA。然后http协议直接写https
结果是可以通过的-----说明后台服务不是异常的,错误还是在发送端。
3. 查看JMeter脚本
查看Linux的脚本,发现了在request参数那里,出现了^M
。出现^M
是因为linux编码不识别\r
,在windows下的 回车换行(\r\n)(CRLF)
到linux下就变成了^M/n
。
想到应该是^M
不认识,那么将^M
去掉,再次执行jmx脚本。发现还是报400。
这时候想起来HTTP的请求标准:需要以/r/n
进行结束。
我竟然傻傻的在请求的末尾加上了 space。然后进行测试,结果当然不通过。其实此时 末尾为 SPLF
。
这时候 我的排查思路出现了偏差,我怀疑了Jar包是不是出现了问题。于是写Java的Demo放到Linux上跑,结果当时是过了。
Linux下的Java编译和运行
我的是同一个package下多个文件。
编译:
javac -encoding "utf-8" -sourcepath /root/ssl_jni/src/ -classpath /root/ssl_jni/classes/ /root/ssl_jni/src/cn/.../anxxx.java -d /root/ssl_jni/classes/
运行:
java -classpath /root/ssl_jni/classes cn/.../anxxx
这使我更加迷惑了,同样的请求内容,为什么JMeter不行,而Java执行却好用呢?其实仔细看,此时请求结尾都是以\r\n结尾的。
但是当时我很迷惑,明明都是一样的字符串,为啥一个好用,一个不好用呢?
于是我将不好用的字符串和 好用的字符串 挨个比Ascll
码,结果我一下子就明白了。
很明显,SP!=CR
直到此时我才明白我犯了错误-----将SP和CR搞混了。
现在就是如何在JMtmer上表达CR
了,受限于Linux,我根本不知道如何在Linux下的文本里表达CR
。
4.峰回路转
我询问了同事,其中有一个同事说,可以看看xml对CR
是怎么处理的。(因为JMeter脚本就是一个XML文件)。
这给了我灵感,我马上看windows下的JMtmer脚本是如何处理CR
,忽然发现JMtmer脚本直接对换行做了HTML编码。
于是我在Linux上对脚本同样做了处理。结果请求成功了!(此时响应码为 500)
5.新问题
请求码报500,提示缺少Body。
此时我请求Body是Json字符串,Jmetr也会做编码。于是我查看了Linux下的JMtmer脚本,发现已经编码了。
又使用Java Demo进行请求。发现也会报 500 ,缺少头。
于是开始抓包,由于是SSL,需要wireshark进行解包,可是私钥是jks,需要导出p12格式的私钥。尤其注意,RSA的加密套件不能是ECDHE的算法,否则无法解析出来报文。
抓包查看了失败报文 和成功的报文对比,发现缺少关键请求头Content-Length
,Content-Length的长度为Body的length,于是在Java Demo中加入了Content-Length
请求可以成功了。
其实这是自己挖的坑,在一开始我会自动添加Content-Type和Content-Length,后来不需要自动添加Content-Type,我就直接也把Content-Length注释掉了。。。。
总结
- JMtmer的
\r
需要进行编码 编码为
- POST请求,最好一定要带上
Content-Length
,Content-Type
- SP 和 CR 不是一个东西 CR是回车,SP是空格
- 换行: Windows下为CRLF,Linux下为LF