ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring MVC 解析JSON入参意外的丢失参数

2021-09-11 03:31:41  阅读:253  来源: 互联网

标签:xss 15 core Spring 09 入参 JSON common XNIO


表现

有如下两个接口:

@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 类型枚举, 然后在退出方法后报错

标签:xss,15,core,Spring,09,入参,JSON,common,XNIO
来源: https://www.cnblogs.com/bingdie/p/15253593.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有