Spring MVC 解析JSON入参意外的丢失参数
2021/9/11 6:04:52
本文主要是介绍Spring MVC 解析JSON入参意外的丢失参数,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
表现
有如下两个接口:
@PostMapping public R<?> save(@RequestBody @Valid ArticleDTO dto) { return R.ok(service.saveArticle(dto)); } @PutMapping public R<?> updateById(@RequestBody @Valid ArticleDTO dto) { return R.ok(service.updateArticle(dto)); }
类似的请求参数(同一个页面的表单), 保存时 dto 中大部分属性都是 NULL
更新时则没有任何问题,
确认请求参数已发出, Spring MVC org.springframework.web.servlet.DispatcherServlet
中断点还能看到, 到达Controller
中参数丢失
前提条件:
请求参数包含一个特殊属性: coverUrl
与之对应的控制器入参对象中 coverUrl
类型为 String
(AVue Upload 类型表单组件默认值)
{ ... "coverUrl": [], "images": [], ... }
项目中 ....common.xss.core.JacksonXssClean
重写了 com.fasterxml.jackson.databind.JsonDeserializer#deserialize
方法, 处理所有的反序列化
deserialize
方法实现如下:
@Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // XSS filter String text = p.getValueAsString(); if (text == null) { return null; } else if (XssHolder.isEnabled()) { String value = XssUtil.clean(text); log.trace("Json property value:{} cleaned up by mica-xss, current value is:{}.", text, value); return value; } else { return text; } }
万恶之源
JsonParser.getValueAsString()
方法注释:
方法将尝试将当前标记的值转换为{@link java.lang.String}。JSON字符串自然映射;标量值被转换为它们的文本表示形式。如果表示不能转换为字符串值(包括结构化类型,如对象、数组和空令牌),将返回默认值null;没有抛出异常。
当处理到请求参数: coverUrl
的属性 [
时, getValueAsString()
直接返回 null
导致方法退出. 后续没有抛出异常, 而是中断所有解析! 也就导致了 content
属性没能正确赋值
而更新方法携带的 coverUrl 属性是查询是返回的, 默认为 NULL, 会跳过 deserialize()
方法的解析. 如果查询结果 coverUrl
非 NULL, 再次提交同样会丢失 coverUrl
之后解析的所有属性 (解析顺序未知, 和入参类型属性的定义顺序, 请求参数的传递顺序 无关)
2021-09-11 02:15:23.502 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : JSON Token 当前属性名 当前值 当前文本 ValueAsString(NULL) VALUE_STRING type ArticleDTO(images=null) 2 2 2021-09-11 02:15:23.624 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : 触发XSS过滤, 原: 2 过滤后: 2 2021-09-11 02:15:23.625 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : JSON Token 当前属性名 当前值 当前文本 ValueAsString(NULL) VALUE_STRING title ArticleDTO(images=null) 文章标题 文章标题 2021-09-11 02:15:23.625 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : 触发XSS过滤, 原: 文章标题 过滤后: 文章标题 2021-09-11 02:15:23.625 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : JSON Token 当前属性名 当前值 当前文本 ValueAsString(NULL) START_ARRAY coverUrl NULL [ [ 2021-09-11 02:15:23.625 ERROR 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : 下一个令牌: END_ARRAY 2021-09-11 02:15:23.625 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : 触发XSS过滤, 原: [ 过滤后: [ 2021-09-11 02:15:23.626 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : JSON Token 当前属性名 当前值 当前文本 ValueAsString(NULL) VALUE_STRING profile ArticleDTO(images=[]) 2021-09-11 02:15:23.626 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : 触发XSS过滤, 原: 过滤后: 2021-09-11 02:15:23.626 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : JSON Token 当前属性名 当前值 当前文本 ValueAsString(NULL) VALUE_STRING content ArticleDTO(images=[]) <p>详情内容</p> <p>详情内容</p> 2021-09-11 02:15:23.629 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : 触发XSS过滤, 原: <p>详情内容</p> 过滤后: <p>详情内容</p> 2021-09-11 02:15:23.631 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : JSON Token 当前属性名 当前值 当前文本 ValueAsString(NULL) VALUE_STRING visibleStatus ArticleDTO(images=[]) 0 0 2021-09-11 02:15:23.632 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : 触发XSS过滤, 原: 0 过滤后: 0 2021-09-11 02:15:23.633 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : JSON Token 当前属性名 当前值 当前文本 ValueAsString(NULL) VALUE_STRING validStatus ArticleDTO(images=[]) 0 0 2021-09-11 02:15:23.633 WARN 10560 --- [ XNIO-1 task-1] n.v.gms.common.xss.core.JacksonXssClean : 触发XSS过滤, 原: 0 过滤后: 0 2021-09-11 02:15:23.775 INFO 10560 --- [ XNIO-1 task-1] n.v.g.cms.controller.ArticleController : 新增文章: {"visitorTotal":0,"images":[],"profile":"","sort":9999,"title":"文章标题","type":"2","content":"<p>详情内容</p>","coverUrl":"[","visibleStatus":"0","validStatus":"0","channelId":0}
解决方案
前端页面
删除 coverUrl
属性即可
后端
一个有限的解决方案, 只能处理空数组, 修改 deserialize
方法实现:
@Override public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException { // XSS filter // String text = p.getValueAsString(); // Method can be called for any token type. String text = p.getText(); // 当前 token 为数组开始字符 if (p.isExpectedStartArrayToken()) { // 快进到下一个 token JsonToken jsonToken = p.nextToken(); } if (text == null) { return null; } else if (XssHolder.isEnabled()) { String value = XssUtil.clean(text); log.trace("Json property value:{} cleaned up by mica-xss, current value is:{}.", text, value); return value; } else { return text; } }
对于非空数组, if 中的 jsonToken
会得到 com.fasterxml.jackson.core.JsonToken#VALUE_STRING
类型枚举, 然后在退出方法后报错
这篇关于Spring MVC 解析JSON入参意外的丢失参数的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23Springboot应用的多环境打包入门
- 2024-11-23Springboot应用的生产发布入门教程
- 2024-11-23Python编程入门指南
- 2024-11-23Java创业入门:从零开始的编程之旅
- 2024-11-23Java创业入门:新手必读的Java编程与创业指南
- 2024-11-23Java对接阿里云智能语音服务入门详解
- 2024-11-23Java对接阿里云智能语音服务入门教程
- 2024-11-23JAVA对接阿里云智能语音服务入门教程
- 2024-11-23Java副业入门:初学者的简单教程
- 2024-11-23JAVA副业入门:初学者的实战指南