安全矩阵

 找回密码
 立即注册
搜索
查看: 817|回复: 0

研读Tomcat源码来看URI处理特性

[复制链接]

252

主题

252

帖子

1309

积分

金牌会员

Rank: 6Rank: 6

积分
1309
发表于 2023-1-3 12:46:05 | 显示全部楼层 |阅读模式
原文链接:研读Tomcat源码来看URI处理特性




前言
这里通过阅读源码和黑盒测试相结合的方式来更加透彻的了解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】师傅


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-29 02:53 , Processed in 0.016434 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表