Spring WebFlux参数处理与Content-type绕过分析
1. Spring WebFlux概述
Spring WebFlux是Spring Framework提供的用于构建响应式Web应用的模块,基于Reactive编程模型实现。它使用了Reactive Streams规范,并提供了一套响应式的Web编程模型,以便于处理高并发、高吞吐量的Web请求。
2. 参数处理过程分析
2.1 请求处理流程
-
前端控制器:DispatcherHandler
- 遍历HandlerMapping数据结构
- 封装成数据流类Flux
- 触发对应的handler方法
- 根据跨域配置信息处理请求
-
参数解析入口:
org.springframework.web.reactive.result.method.InvocableHandlerMethod#invoke- 调用
getMethodArgumentValues方法处理参数 - 遍历已配置的解析器列表进行匹配
- 调用
2.2 解析器匹配机制
通过org.springframework.web.reactive.result.method.HandlerMethodArgumentResolverComposite#getArgumentResolver判断:
- 默认有24个Resolver处理器
- 每个解析器调用
supportsParameter方法判断是否支持给定参数类型 - 未找到匹配解析器时抛出异常
示例:PathVariableMethodArgumentResolver的匹配条件是存在@PathVariable注解
2.3 请求体解析过程
RequestBodyMethodArgumentResolver#resolveArgument调用流程:
- 调用
readBody方法处理请求体 - 排除
Content-Type: application/x-www-form-urlencoded请求 - 获取所有可用的
HttpMessageReader实例 - 遍历实例,通过
canRead检查是否能读取当前请求内容类型 - 调用匹配的
HttpMessageReader的read方法读取和转换请求体
3. Content-type处理机制
3.1 JSON请求处理
org.springframework.http.codec.json.AbstractJackson2Decoder#canDecode:
- 对mimeType进行一系列检查
- 最终确定是否能够解码请求体
3.2 form-data请求处理
特殊处理:
@RequestParam注解仅支持URL传参方式- 无法直接处理form-data和multipart请求
- 需要通过
ServerWebExchange处理
示例代码:
@PostMapping("/users")
public Mono<String> getUser(ServerWebExchange exchange) {
return exchange.getFormData()
.flatMap(formData -> {
String paramName = formData.getFirst("param");
return Mono.just("Param: " + paramName);
});
}
4. Spring WebFlux与Spring MVC的差异
关键区别:
-
通配符类型处理:
- Spring MVC限制不能是通配符类型(wildcard type)
- Spring WebFlux无此检查机制
-
解析流程:
- WebFlux获取所有可用
HttpMessageReader实例 - 遍历检查是否能读取当前请求内容类型
- 直接调用匹配的
read方法转换请求体
- WebFlux获取所有可用
5. Content-type绕过思路
5.1 supportedMediaTypes匹配绕过
-
JSON变体:
Jackson2JsonDecoder可解析application/*+json- 如
application/x-ndjson
-
通配符使用:
- 将
application/x-www-form-urlencoded替换为:*/*application/*
- 将
5.2 Multipart解析差异
利用fileName解析特点,在特定场景下绕过安全检查。
5.3 Content-type畸形构造
基于org.springframework.util.MimeTypeUtils#parseMimeTypeInternal处理逻辑:
-
处理方式:
- 找到第一个分号位置
- 提取分号前部分并去除首尾空格
- 提取type和subtype
- 解析参数部分并存储到LinkedHashMap
- 统一将type&subtype转换成小写
-
构造技巧:
- 使用大写Content-Type
- 加入额外空格
- 在分号后加入额外内容
- 结合supportedMediaTypes匹配
示例畸形Content-type:
APPLICATION/JSON; charset=UTF-8; extra=param
6. 安全建议
- 严格验证所有输入参数
- 实现自定义过滤器进行内容类型检查
- 限制允许的Content-type范围
- 对大小写不敏感的内容类型进行规范化处理
- 注意处理边界情况和异常输入
7. 总结
Spring WebFlux的参数处理机制与Spring MVC存在显著差异,特别是在Content-type处理方面更为灵活。这种灵活性虽然提高了框架的适应性,但也可能带来潜在的安全风险。理解这些差异和潜在的绕过方式,有助于开发更安全的Web应用。