Spring REST控制器无法处理含转义HTML的XML负载问题排查
问题:XML负载中的转义字符导致Spring控制器请求参数拆分/截断
我正在开发一个Spring控制器,作为我方无法控制的第三方平台的事件订阅者。当该平台创建或更新内容时,会向指定回调URL发送POST请求,请求包含变更信息(含内容主体)。但控制器接收请求时,XML负载中的转义HTML字符导致文档被破坏,进而引发XML解析问题。
简化后的控制器代码
@RestController public class Controller { @PostMapping(path = "/listenerOne") public ResponseEntity<String> listenerOne( @RequestParam(name = "event.type") final String eventType, @RequestParam(name = "message", required = false) final String xmlPayload) { return ResponseEntity.ok().body(xmlPayload); } @PostMapping(path = "/listenerTwo", consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE}) public ResponseEntity<String> listenerTwo(@RequestBody final MultiValueMap<String, String> messageEvent) { return ResponseEntity.ok().body(messageEvent.toString()); } }
请求参数示例(message-event.xml)
<message type="message" href="/messages/id/1313133"> <body type="string"><P>Test body</P></body> <subject type="string">Test message</subject> <id type="int">1313133</id> </message>
测试curl命令及结果
测试/listenerOne
curl -XPOST localhost:8080/listenerOne -d "event.type=MessageUpdate&message=$(cat message-event.xml)"
返回结果:
<message type="message" href="/messages/id/1313133"> <body type="string">%
测试/listenerTwo
curl -XPOST localhost:8080/listenerTwo -d "event.type=MessageUpdate&message=$(cat message-event.xml)"
返回结果:
{event.type=[MessageUpdate], message=[<message type="message" href="/messages/id/1313133"> <body type="string">], lt;P=[], gt;Test body=[], lt;/P=[], gt;</body> <subject type=["string">Test message</subject> <id type="int">1313133</id> </message>]}%
可见<body type="string">之后的内容被截断或拆分,请问为何会出现请求体/参数拆分的情况?
原因分析
问题核心在于**application/x-www-form-urlencoded格式的参数解析规则冲突**:
- URL编码规则的影响
application/x-www-form-urlencoded格式要求参数值中的特殊字符(如&、=、%)必须做URL编码。而XML里的<是XML转义字符,但在URL编码语境下,&是参数分隔符。当未编码的&出现在参数值中时,会被解析成参数分隔符,导致原本属于message参数的内容被拆分成多个无效参数:
message参数只拿到<body type="string">部分- 后续的
lt;P、gt;Test body等被误判为新的空值参数
curl命令的直接拼接问题
你用$(cat message-event.xml)直接将XML内容插入curl的-d参数中,curl会把XML里的&当作参数分隔符处理,而非message参数值的一部分,这直接引发了参数截断和拆分。Spring的参数解析逻辑
Spring处理application/x-www-form-urlencoded请求时,会严格遵循URL编码规则拆分参数。一旦遇到未编码的&,就会判定为新参数的起始点,自然会把原message参数的内容拆解得支离破碎。
内容的提问来源于stack exchange,提问作者Steven Spasbo
相关产品推荐
相关产品推荐

