JSON格式提交的数据怎么防SQL注入_在反序列化后进行强类型绑定

夏杰小哥_3401

夏杰小哥_3401

2026-05-07

849人浏览

原创

强类型绑定本身不防sql注入,仅确保数据结构可控;真正起防护作用的是后续配合参数化查询,使用户输入与sql语义隔离,二者缺一不可。

json格式提交的数据怎么防sql注入_在反序列化后进行强类型绑定

反序列化后做强类型绑定,本身不防SQL注入,但它是防止注入的关键前置动作。真正起防护作用的是后续对绑定后字段的使用方式——如果仍用字符串拼接构造 SQL,强类型绑定毫无意义;只有配合参数化查询,它才构成完整防线。

为什么强类型绑定不能直接防SQL注入

强类型绑定(如 Spring 的 @RequestBody User user、Jackson 的 ObjectMapper.readValue(json, User.class))只解决「把 JSON 字符串转成 Java/Go/PHP 对象」这件事。它能校验字段名、类型、非空等,但不会过滤或转义内容本身。

比如:{"name": "admin'; DROP TABLE users; -- "} 反序列化后得到一个 User.name 字段值仍是那个恶意字符串。若你随后写:"SELECT * FROM users WHERE name = '" + user.getName() + "'",照样中招。

常见错误现象:

  • 接口返回 500 或数据库报错,但日志里看到执行了 DROP、UNION SELECT 等语句
  • 前端传 {"id": "1 OR 1=1"},后端查出全表数据
  • 强类型校验通过了,但 SQL 执行异常或结果不符合预期

强类型绑定必须搭配参数化查询才有效

绑定只是让数据「结构可控」,参数化查询才是让数据「语义隔离」。两者缺一不可。

正确做法示例(Java + MyBatis):

@Select("SELECT * FROM users WHERE id = #{id} AND status = #{status}")
User selectByIdAndStatus(@Param("id") Long id, @Param("status") String status);

关键点:

Json Schema Toolkit
Json Schema Toolkit

使用 JSON Schema 验证 JSON 数据,从示例 JSON 生成 schema,并将其转换为 TypeScript 接口、Python 数据类或 Markdown 文档。

下载
  • #{id} 是预编译占位符,MyBatis 自动转为 ? 并调用 PreparedStatement.setLong()
  • 即使 user.getId() 是 1 OR 1=1,它也只会被当作整数 1 处理(类型不匹配时抛异常,而非拼进 SQL)
  • 字符串字段同理:#{name} 会走 setString(),单引号、分号、注释符全部失去 SQL 语法意义

JSON 深层嵌套或动态字段怎么办

强类型绑定天然适合固定结构。遇到 content: {"custom_field": "xxx"} 这类 JSONB 或动态字段,不能靠绑定防注入——因为字段名和路径本身来自用户输入。

此时必须放弃「直接拼接 JSON 路径到 SQL」的做法。例如 PostgreSQL 中禁止这样写:

WHERE content->>'" + userInputPath + "' = '" + userInputValue + "'"

替代方案:

  • 对允许的 JSON 路径做白名单限制(如只允许 ["title", "author", "tags"])
  • 用函数参数化路径:PostgreSQL 支持 jsonb_extract_path_text(content, VARIADIC string_to_array(?, '.')),其中 ? 是用户输入的路径字符串,由驱动安全传入
  • Go 中可用 pgx.QueryRow(ctx, "SELECT ... WHERE data->>$1 = $2", path, value),$1 和 $2 都是参数化位置

最容易被忽略的环节:JSON 中的数字/布尔字段也得走参数化

很多人以为只有字符串要防,其实数字、布尔、null 同样危险。比如:

前端传:{"limit": "10; DROP TABLE logs;"},后端若写:"LIMIT " + req.getLimit(),就完蛋。

正确姿势:

  • 所有从 JSON 解析出的字段,无论类型,只要进 SQL,就必须进 PreparedStatement / #{} / $1 占位符
  • 不要用 toString() 或 String.valueOf() 再拼 SQL —— 这等于绕过所有防护
  • ORM 如 Hibernate、SQLAlchemy 默认对所有映射字段使用参数化,但手动写原生 SQL 时,必须自己确保每个变量都用参数传入

复杂点在于:强类型绑定和参数化查询是两个独立步骤,中间夹着业务逻辑。一旦在 service 层做了字符串拼接,前面的绑定就白做了。防注入不是加个注解就能一劳永逸的事。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

3943

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

851

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

1029

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

5781

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

2723

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

5760

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

7641

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

1050

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

912

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WEB前端教程【HTML5+CSS3+JS】
WEB前端教程【HTML5+CSS3+JS】

共101课时 | 20.7万人学习

JS进阶与BootStrap学习
JS进阶与BootStrap学习

共39课时 | 4.8万人学习