浅谈SpringMVC参数处理过程
字数 2382 2025-08-06 08:34:54

Spring MVC 参数处理机制深度解析

0x00 概述

Spring MVC 通过参数解析机制简化了传统 Java Web 开发中通过 HttpServletRequest.getParameter() 获取请求参数的方式。开发者只需在 Controller 方法中定义参数,Spring MVC 会自动完成参数解析、类型转换和校验。

0x01 请求参数解析流程

1.1 请求处理入口

  1. DispatcherServlet.service():Servlet 容器接收请求后调用

    • 位于 FrameworkServlet 父类中实现
    • 除 PATCH 方法外,其他 HTTP 方法都通过 HttpServlet.service() 处理
  2. processRequest():根据请求方法调用对应处理

    • GET → doGet()
    • POST → doPost()
    • 其他方法类似
  3. doDispatch():核心分发方法

    • 处理 multipart 请求
    • 获取 URL 与 Handler 的映射关系
    • 根据 URI 找到对应的 Controller 和方法

1.2 Handler 适配与执行

  1. 获取 HandlerAdapter:找到适合处理当前请求的适配器

    • 调用 handle() 方法处理请求
    • 实际执行 handleInternal()
  2. 请求检查与会话同步

    • 检查请求有效性
    • 必要时在会话级别进行同步
      • 获取 HttpSession
      • 获取互斥对象进行同步
  3. invokeHandlerMethod():执行实际请求处理

    • 封装 ServletWebRequest(包含 HttpServletRequestHttpServletResponse
    • 获取 DataBinderFactoryModelFactory
    • 创建 ServletInvocableHandlerMethod 执行方法调用

1.3 参数解析核心过程

  1. invokeForRequest():调用 Controller 方法

    • 通过 getMethodArgumentValues() 获取方法参数值
  2. 参数解析步骤

    • 获取方法参数列表
    • 遍历参数列表:
      • 检查 providedArgs 中是否有预定义参数
      • 使用合适的参数解析器解析参数
  3. 解析器查找机制

    • 检查缓存中是否有适用的解析器
    • 遍历已配置的解析器列表(约28个)
    • 调用解析器的 supportsParameter() 判断是否支持当前参数
    • 找到后缓存并返回解析器
  4. 参数解析执行

    • 调用解析器的 resolveArgument() 方法
    • 处理参数类型转换、绑定和验证

0x02 参数解析器详解

2.1 常见解析器类型

  1. RequestParamMapMethodArgumentResolver

    • 解析条件:@RequestParam 注解 + Map 类型参数
    • 示例:@RequestParam Map<String, String> params
  2. RequestParamMethodArgumentResolver

    • 解析条件:
      • @RequestParam 注解 + 非 Map 类型
      • 基本类型及其包装类(String, Number, Date 等)
      • 可选请求参数(required=falseOptional
    • 示例:
      @RequestParam("param") String param
      @RequestParam(required = false) Integer id
      @RequestParam Optional<String> name
      
  3. PathVariableMethodArgumentResolver

    • 解析 @PathVariable 注解参数
  4. RequestPartMethodArgumentResolver

    • 解析 @RequestPart 注解参数(文件上传等)

2.2 参数解析细节

2.2.1 普通参数解析

  1. resolveName() 方法处理流程:

    • 获取原生 HttpServletRequest
    • 处理 multipart 请求(文件上传)
    • 普通参数通过 request.getParameterValues(name) 获取
  2. HTTP 参数污染(HPP)处理

    • Tomcat 默认取第一个参数值
    • Spring 返回参数值数组
    • 示例:param=1&param=2 → 返回 ["1", "2"]

2.2.2 安全绕过示例

  1. SQL 注入绕过技术

    • 利用参数解析特性拆分恶意 payload
    • 示例:
      1/(case+when+ascii(substr(user,1,1))=112+then+1+else+0+end)
      
    • 拆分方式:
      param=1/(case+when+ascii(substr(user&param=1,1,1))=112+then+1+else+0+end)
      
    • 效果:
      • ASCII 111 → 触发除零异常
      • ASCII 112 → 正常返回
  2. WAF 绕过原理

    • 利用解析器返回 Object 类型的灵活性
    • 拆分敏感函数(如 substr())绕过关键词检测

0x03 其他重要解析器

  1. MatrixVariableMethodArgumentResolver

    • 解析矩阵变量(URI 路径中的 ; 分隔参数)
  2. RequestHeaderMethodArgumentResolver

    • 解析 @RequestHeader 注解参数
  3. CookieValueMethodArgumentResolver

    • 解析 @CookieValue 注解参数
  4. ModelAttributeMethodProcessor

    • 处理 @ModelAttribute 注解参数

0x04 总结

Spring MVC 参数处理机制的核心特点:

  1. 灵活的参数解析:通过多种解析器支持各种参数类型和注解
  2. 自动类型转换:基本类型、包装类、日期等自动转换
  3. 扩展性强:可自定义参数解析器实现特殊需求
  4. 安全考量:需注意参数解析过程中的安全边界,特别是 HPP 等场景

开发建议:

  • 明确参数类型和注解使用
  • 对敏感参数进行额外验证
  • 了解解析器特性以避免意外行为
  • 在安全防护中考虑参数解析机制的影响
Spring MVC 参数处理机制深度解析 0x00 概述 Spring MVC 通过参数解析机制简化了传统 Java Web 开发中通过 HttpServletRequest.getParameter() 获取请求参数的方式。开发者只需在 Controller 方法中定义参数,Spring MVC 会自动完成参数解析、类型转换和校验。 0x01 请求参数解析流程 1.1 请求处理入口 DispatcherServlet.service() :Servlet 容器接收请求后调用 位于 FrameworkServlet 父类中实现 除 PATCH 方法外,其他 HTTP 方法都通过 HttpServlet.service() 处理 processRequest() :根据请求方法调用对应处理 GET → doGet() POST → doPost() 其他方法类似 doDispatch() :核心分发方法 处理 multipart 请求 获取 URL 与 Handler 的映射关系 根据 URI 找到对应的 Controller 和方法 1.2 Handler 适配与执行 获取 HandlerAdapter :找到适合处理当前请求的适配器 调用 handle() 方法处理请求 实际执行 handleInternal() 请求检查与会话同步 检查请求有效性 必要时在会话级别进行同步 获取 HttpSession 获取互斥对象进行同步 invokeHandlerMethod() :执行实际请求处理 封装 ServletWebRequest (包含 HttpServletRequest 和 HttpServletResponse ) 获取 DataBinderFactory 和 ModelFactory 创建 ServletInvocableHandlerMethod 执行方法调用 1.3 参数解析核心过程 invokeForRequest() :调用 Controller 方法 通过 getMethodArgumentValues() 获取方法参数值 参数解析步骤 : 获取方法参数列表 遍历参数列表: 检查 providedArgs 中是否有预定义参数 使用合适的参数解析器解析参数 解析器查找机制 : 检查缓存中是否有适用的解析器 遍历已配置的解析器列表(约28个) 调用解析器的 supportsParameter() 判断是否支持当前参数 找到后缓存并返回解析器 参数解析执行 : 调用解析器的 resolveArgument() 方法 处理参数类型转换、绑定和验证 0x02 参数解析器详解 2.1 常见解析器类型 RequestParamMapMethodArgumentResolver 解析条件: @RequestParam 注解 + Map 类型参数 示例: @RequestParam Map<String, String> params RequestParamMethodArgumentResolver 解析条件: @RequestParam 注解 + 非 Map 类型 基本类型及其包装类(String, Number, Date 等) 可选请求参数( required=false 或 Optional ) 示例: PathVariableMethodArgumentResolver 解析 @PathVariable 注解参数 RequestPartMethodArgumentResolver 解析 @RequestPart 注解参数(文件上传等) 2.2 参数解析细节 2.2.1 普通参数解析 resolveName() 方法处理流程: 获取原生 HttpServletRequest 处理 multipart 请求(文件上传) 普通参数通过 request.getParameterValues(name) 获取 HTTP 参数污染(HPP)处理 : Tomcat 默认取第一个参数值 Spring 返回参数值数组 示例: param=1&param=2 → 返回 ["1", "2"] 2.2.2 安全绕过示例 SQL 注入绕过技术 : 利用参数解析特性拆分恶意 payload 示例: 拆分方式: 效果: ASCII 111 → 触发除零异常 ASCII 112 → 正常返回 WAF 绕过原理 : 利用解析器返回 Object 类型的灵活性 拆分敏感函数(如 substr() )绕过关键词检测 0x03 其他重要解析器 MatrixVariableMethodArgumentResolver 解析矩阵变量(URI 路径中的 ; 分隔参数) RequestHeaderMethodArgumentResolver 解析 @RequestHeader 注解参数 CookieValueMethodArgumentResolver 解析 @CookieValue 注解参数 ModelAttributeMethodProcessor 处理 @ModelAttribute 注解参数 0x04 总结 Spring MVC 参数处理机制的核心特点: 灵活的参数解析 :通过多种解析器支持各种参数类型和注解 自动类型转换 :基本类型、包装类、日期等自动转换 扩展性强 :可自定义参数解析器实现特殊需求 安全考量 :需注意参数解析过程中的安全边界,特别是 HPP 等场景 开发建议: 明确参数类型和注解使用 对敏感参数进行额外验证 了解解析器特性以避免意外行为 在安全防护中考虑参数解析机制的影响