SQL注入中ORDER BY排序怎么动态传参_采用白名单映射字段名

P粉602998670

P粉602998670

2026-04-28

618人浏览

原创

dapper动态排序必须用白名单校验字段名再安全拼接,因数据库引擎不支持order by参数化,否则将导致排序失效或sql注入。

sql注入中order by排序怎么动态传参_采用白名单映射字段名

动态传参给 ORDER BY 本身不支持参数化,必须用白名单映射字段名——这是防止 SQL 注入的刚性要求,不是可选项。

为什么不能直接用 ? 或 #{ } 给 ORDER BY 传字段名

数据库引擎(SQL Server、PostgreSQL、MySQL)明确区分「值」和「标识符」:参数占位符(如 ?@p#{field})只接受数据值,不能替换列名、表名或关键字。一旦强行传入,实际执行的是 ORDER BY 'user_id' 这类语句——字符串字面量恒为相同值,排序失效,且可能报类型转换错误(比如把 'created_at' 当字符串跟 datetime 列比)。

常见错误现象包括:

  • 查询结果完全无序,或所有行排在同一位置
  • 报错如 Conversion failed when converting the varchar value 'status' to data type int
  • MyBatis 中写成 ORDER BY #{orderBy},日志显示生成了带单引号的 ORDER BY 'name'

白名单映射字段名的三种安全落地方式

核心逻辑:用户传来的字段名(如 "sort=price")不直接拼接,而是查表/枚举/配置,映射到预设合法字段,再拼进 SQL。

防SQL注入的php类库
防SQL注入的php类库

防SQL注入的php类库

下载
  • 硬编码白名单 + if/else 或 switch:适合字段极少(≤5)、几乎不变的场景,例如 if ("price".equals(input)) { sql += " ORDER BY price"; }
  • Map 静态映射:Java 中定义 Map<string string> SORT_MAP = Map.of("price", "price", "name", "product_name", "date", "created_at");</string>,校验 SORT_MAP.containsKey(input) 后取值拼接
  • 数据库元数据校验:运行时查 INFORMATION_SCHEMA.COLUMNS 确认字段真实存在且属于目标表,但需额外权限,响应慢,一般用于管理后台等低频场景

升降序控制别传字符串 'ASC'/'DESC',改用布尔或 BIT

方向参数同样不能无条件拼接,否则 ORDER BY name ${sortDir} 可能被注入为 ORDER BY name; DROP TABLE users--。正确做法是限定输入值,并用逻辑控制拼接:

  • 前端只允许传 sort_dir=true(升序)或 false(降序),后端转成 "ASC""DESC" 字符串
  • SQL Server 存储过程中用 @sort_dir BIT,配合 CASE WHEN @sort_dir = 1 THEN name END DESC, CASE WHEN @sort_dir = 0 THEN name END ASC ——避免字符串拼接,也兼容执行计划缓存
  • MyBatis 中用 <if test="sortDir == 'asc'">ASC</if><if test="sortDir == 'desc'">DESC</if>,前提是 sortDir 已在 Controller 层校验过

MyBatis 和 Dapper 里最易忽略的坑

很多人以为用了 MyBatis 的 ${} 或 Dapper 的字符串插值就“搞定了”,其实只是把拼接点从 Java 移到了 XML 或 C# 里,注入风险照旧。

  • MyBatis 的 ${param.sortField} 必须前置校验:Controller 中调用 Assert.isTrue(SORT_FIELDS.contains(param.getSortField())),而不是只在 XML 里 <if test="sortField == 'id'"></if> ——后者不防绕过
  • Dapper 执行前必须做白名单判断:if (!new[] { "id", "email", "created" }.Contains(sortColumn)) throw new ArgumentException("Invalid sort column");
  • PostgreSQL 的 psycopg 若用 f-string 拼接,k 必须已通过 if k not in ["price", "year"]: raise ValueError 校验,绝不可依赖客户端传值

真正容易被忽略的,是白名单校验的位置——它必须发生在 SQL 构造之前、且不可被跳过;任何“先拼再校”或“仅前端校验”的设计,都等于没设防。

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

sql注入

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

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

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

2023.10.12

2451

8

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

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

2023.10.27

448

4

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

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

2024.02.23

614

5

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

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

2024.03.06

3968

10

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

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

2024.03.06

1344

4

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

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

2024.04.07

3561

11

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

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

2024.04.29

3490

6

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

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

2024.04.29

641

5

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

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

2024.04.29

526

5

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP开发基础之数据库篇(PDO)
PHP开发基础之数据库篇(PDO)

共10课时 | 2.2万人学习