研读Tomcat源码来看URI处理特性
字数 1785 2025-08-26 22:11:51

Tomcat URI处理特性源码分析

前言

本文通过阅读Tomcat源码和黑盒测试相结合的方式,深入分析Tomcat对URI的处理特性,包括path parameters解析和URI规范化(normalize)处理逻辑。

主要处理流程

Tomcat处理请求的主要逻辑位于:

  1. org.apache.coyote.http11.Http11Processor#service - Processor层服务
  2. CoyoteAdapter#service - 请求转发到Adapter
  3. postParseRequest - 核心解析方法

parsePathParameters处理逻辑

处理流程

  1. 首先从Request对象获取URI
  2. 对URI进行解码操作
  3. 调用duplicate方法将原始URI(undecodedURI)复制到解码后的URI
  4. 调用parsePathParameters方法解析path parameters

parsePathParameters方法细节

  1. 将URI转化为字节数组并获取ByteChunk对象
  2. 检查URI中是否存在;分隔符
  3. 获取URI的开始下标、结束下标、pathParam的开始和结束下标
    • pathParamEnd通过遍历字节数组查找分隔符(;/)
    • 如果找不到返回-1,否则返回偏移地址

处理规则

  1. 如果在第一个;后面出现分隔符:

    • 将第一个;之后的所有字符串赋给pv变量
    • 设置结束位置
    • pv中的字符串以等号分隔,分别取左右值
    • 调用addPathParameter添加到org.apache.coyote.Request类的pathParameters属性中
  2. 如果后面出现分隔符:

    • 循环获取pv
    • 调用addPathParameter添加

测试案例总结

输入URI 解析结果
/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处理逻辑

处理流程

  1. 调用req.getURLDecoder().convert对URI进行URL解码
    • 在URI的Byte数组中查找%并进行解码
  2. 调用normalize方法进行规范化处理

normalize方法细节

  1. 基本检查:

    • 如果URI开始偏移等于结束偏移,返回400状态码
    • 如果URI首字符不是/也不是\,返回400状态码
  2. 字符处理:

    • 存在\ALLOW_BACKSLASH为true时替换为/
    • 存在\u0000字符直接返回400
  3. 特殊路径处理:

    • /./开头转化为/
    • /../开头直接转化为/

测试案例

输入URI 解析结果
/upload/ /upload/
/upload/upload/ /upload/upload/
/./upload/ /upload/
/../upload/ /upload/
\upload/ /upload/
\upload/ /upload/

总结

Tomcat对URI的处理主要包括两个关键部分:

  1. Path Parameters解析

    • 处理以;分隔的路径参数
    • 遵循特定规则舍弃或保留部分URI内容
  2. URI规范化

    • 处理特殊字符和路径
    • 确保URI格式符合规范
    • 对潜在危险输入进行过滤

理解这些处理特性对于开发安全的Web应用和进行安全测试都非常重要,特别是在处理用户输入和路径解析时。

Tomcat URI处理特性源码分析 前言 本文通过阅读Tomcat源码和黑盒测试相结合的方式,深入分析Tomcat对URI的处理特性,包括path parameters解析和URI规范化(normalize)处理逻辑。 主要处理流程 Tomcat处理请求的主要逻辑位于: org.apache.coyote.http11.Http11Processor#service - Processor层服务 CoyoteAdapter#service - 请求转发到Adapter postParseRequest - 核心解析方法 parsePathParameters处理逻辑 处理流程 首先从Request对象获取URI 对URI进行解码操作 调用 duplicate 方法将原始URI(undecodedURI)复制到解码后的URI 调用 parsePathParameters 方法解析path parameters parsePathParameters方法细节 将URI转化为字节数组并获取ByteChunk对象 检查URI中是否存在 ; 分隔符 获取URI的开始下标、结束下标、pathParam的开始和结束下标 pathParamEnd 通过遍历字节数组查找分隔符( ; 或 / ) 如果找不到返回-1,否则返回偏移地址 处理规则 如果在第一个 ; 后面出现分隔符: 将第一个 ; 之后的所有字符串赋给 pv 变量 设置结束位置 将 pv 中的字符串以等号分隔,分别取左右值 调用 addPathParameter 添加到 org.apache.coyote.Request 类的 pathParameters 属性中 如果后面出现分隔符: 循环获取 pv 值 调用 addPathParameter 添加 测试案例总结 | 输入URI | 解析结果 | |---------|----------| | /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处理逻辑 处理流程 调用 req.getURLDecoder().convert 对URI进行URL解码 在URI的Byte数组中查找 % 并进行解码 调用 normalize 方法进行规范化处理 normalize方法细节 基本检查: 如果URI开始偏移等于结束偏移,返回400状态码 如果URI首字符不是 / 也不是 \ ,返回400状态码 字符处理: 存在 \ 且 ALLOW_BACKSLASH 为true时替换为 / 存在 \u0000 字符直接返回400 特殊路径处理: 以 /./ 开头转化为 / 以 /../ 开头直接转化为 / 测试案例 | 输入URI | 解析结果 | |---------|----------| | /upload/ | /upload/ | | /upload/upload/ | /upload/upload/ | | /./upload/ | /upload/ | | /../upload/ | /upload/ | | \upload/ | /upload/ | | \\upload/ | /upload/ | 总结 Tomcat对URI的处理主要包括两个关键部分: Path Parameters解析 : 处理以 ; 分隔的路径参数 遵循特定规则舍弃或保留部分URI内容 URI规范化 : 处理特殊字符和路径 确保URI格式符合规范 对潜在危险输入进行过滤 理解这些处理特性对于开发安全的Web应用和进行安全测试都非常重要,特别是在处理用户输入和路径解析时。