前言
这里通过阅读源码和黑盒测试相结合的方式来更加透彻的了解Tomcat的url解析策略
parsePathParameters处理逻辑
Tomcat在处理每一次的请求的时候,主要的处理逻辑是在org.apache.coyote.http11.Http11Processor#service
方法中进行对应的Processor层的服务
之后将会将请求转发到Adapter
中去进行接下来的逻辑
这里主要是CoyoteAdapter#service
方法中
进行请求的处理,而我们这篇文章中关注的有关于url解析的特点主要集中在该方法中调用了postParseRequest
方法进行解析
跟进这个方法的调用,看看具体的逻辑是什么
这里将会判断req.scheme().isNull
的返回值
如果不为空,也即是req.scheme
返回的是https
,则将会设置secure
属性值为true
反之,如果为空,也即是http
请求,将会将属性值设置为false
接下来的逻辑就是有代理就设置代理,没有的话,将会判断tomcat有没有对端口进行配置,如果这里是通过https进行请求,将会将服务端口设置为443,反之就是默认端口80
我这里的tomcat配置了端口为8080的,所以不会进入这个if语句
接下来就是从Request
对象中获取到了请求的URI,首先判断这个URI是不是*
这里主要是用来检查ping OPTTIONS * request用的
再然后首先对URI进行进行了解码操作,之后再进入if语句之后,调用duplicate
方法将原始的URI,也即是undecodedURI
复制到解码后的URI中去
之后调用parsePathParameters
方法进行path parameters的解析操作
首先是对复制过来的原始URI转化为字节数组之后,获取这个URI的ByteChunk对象
之后会判断在这个URI中是否有;
这个分隔符,如果存在有这个分隔符,将会进入这个if语句进行后续的处理
前面主要是获取URI的开始下标,结束下标,pathParam的开始下标,pathParam的结束下标
这里主要看看pathParamEnd的获取方式
主要是遍历bytes参数中的每一个字节,筛选是否有b字节数组中的字节,这个数组也即是分隔符数组,包含有; /
两个字符,如果没有找到,将会返回-1
, 否则返回的是偏移地址
好了,现在回到parsePathParameters方法中的逻辑来
如果在第一个;
后面出现了分隔符,将会进入if语句中去
这里面的逻辑主要是将第一个;
出现之后的所有字符串全部传递给pv
变量,并在之后调用setEnd
设置结束位置
之后将会将pv中的字符串以等号作为分隔符,分别取取等号左边和右边的值,调用addPathParameter
方法添加进入org.apache.coyote.Request
类的pathParameters
属性中去了
而如果这后面出现了分隔符,将会进入else语句中
也就是循环一次一次的获取pv值之后调用addPathParameter
进行添加
这种的方式就有点像如果将sessionID保存在url中的形式
总结
这里可以简单做个总结
-
/upload;test ==> /upload
-
/upload;test/ ==> /upload/
-
/upload;test;/ ==> /upload/
-
/upload;te;st/ ==> /upload/
-
/upload;te/st/ ==> /upload/st/
-
/upload;te/s;t/ ==> /upload/s/
-
/upload;te;s;t/ ==> /upload/
-
/upload;te;s/t/ ==> /upload/t/
这里通过黑白盒的方式,大概可以看出来,
-
在URI中以
;
开头,并且以;
或者/
结尾的地方将会在处理过程中进行舍弃 -
如果URI末尾存在
/
,解析之后的URI一定存在/
normalize处理逻辑
接下来我们回到postParseRequest
方法中继续阅读Tomcat源码
在这里通过调用req.getURLDecoder().convert
方法对URI进行url解码
这里主要是在URI的Byte数组中寻找是否存在有%, 之后进行后续解码操作
之后来到了normalize
方法的调用
这一部分大概的逻辑就是如果URI开始的偏移地址也就是结束的偏移地址,将会返回400状态码,或者如果URI首个字符不是/
的同时也不是\
也会返回400状态码
之后会遍历URI中的所有字符,如果存在有且
ALLOW_BACKSLASH
属性为true的时候将替换为/
,如果存在有u0000
字符,将直接返回400
之后,如果URI是以/./
开头的,将会将其转化为/
如果是以/../
开头的将会直接转化为/
简单测试一下
-
/upload/../ ==> /
-
/upload/./ ==> /upload/
-
/./upload/ ==> /upload/
-
/../upload/ ==> /upload/
-
upload/ ==> /upload/
-
\upload/
==> /upload/
来源:先知社区的【RoboTerh】师傅
注:如有侵权请联系删除
如需进群进行技术交流,请扫该二维码
原文始发于微信公众号(衡阳信安):研读Tomcat源码来看URI处理特性
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论