尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

动态表名怎么安全拼进SQL?sql-template-strings的raw值与escapeId防注入详解

动态表名怎么安全拼进SQL?sql-template-strings的raw值与escapeId防注入详解 动态表名怎么安全拼进SQLsql-template-strings的raw值与escapeId防注入详解【免费下载链接】node-sql-template-stringsES6 tagged template strings for prepared SQL statements 项目地址: https://gitcode.com/gh_mirrors/no/node-sql-template-strings在 Node.js 后端开发中「动态表名」是 SQL 注入的高危场景预编译占位符只能绑定数据值却拼不了表名和列名。开源项目sql-template-strings用一个 ES6 标签模板字符串帮你安全地写出预编译 SQL——普通值自动走?/$1占位符绑定表名这类标识符则用raw 值配合escapeId手动转义一套 API 同时兼容 mysql、mysql2、PostgreSQLpg和 Sequelize。一、为什么预编译挡不住表名注入很多新手以为用了预编译语句prepared statement就万事大吉其实占位符只有一种身份——数据值SELECT * FROM books WHERE author $1 -- ✅ 值是数据安全 SELECT * FROM $1 -- ❌ 表名是语法结构占位符无能为力一旦表名、列名、排序方向来自用户输入直接字符串拼接就像开了后门books; DROP TABLE users--这类输入会直接改变 SQL 结构。这正是 raw 值要解决的问题。二、30 秒看懂 sql-template-strings 的工作原理安装后SQL是一个标签函数const SQL require(sql-template-strings) const query SQLSELECT author FROM books WHERE name ${book} query.sql // SELECT author FROM books WHERE name ? 给 mysql query.text // SELECT author FROM books WHERE name $1 给 PostgreSQL query.values // [book]核心实现就在根目录的index.jsSQLStatement类负责维护字符串片段与values数组append()、setName()、useBind()等方法全部链式返回this。三、动态表名怎么拼raw 值 append()README 说得直白Some values cannot be replaced by placeholders in prepared statements, like table names.有些值无法用占位符替换比如表名。v1 时代的写法是SQL.raw()当前 v2 版本中append()接过了这个职责——给它传一个普通字符串就会原样拼进 SQL不占用位符const table books const order DESC db.query( SQLSELECT * FROM .append(table) .append(SQL ORDER BY rating ) .append(order) ) 要点raw 值就是所见即所得的纯文本库不做任何转义——安全责任在你手里。四、给 raw 值上保险escapeId 与 escapeIdentifier 转义如果表名来自用户输入必须先过一遍驱动自带的标识符转义函数官方 README「Raw values」一节的明确要求// MySQL反引号包裹并转义内部的反引号 mysql.query( SQLSELECT * FROM .append(mysql.escapeId(someUserInput)) .append(SQL WHERE name ${book}) ) // PostgreSQL双引号包裹 pg.query( SQLSELECT * FROM .append(pg.escapeIdentifier(someUserInput)) .append(SQL WHERE name ${book}) )escapeId的作用类似加引号 转义引号books变成books而恶意输入books; DROP TABLE users-- 会被整体包成一个无害的标识符字符串再也无法改变 SQL 结构。五、更稳的做法白名单校验转义是兜底白名单才是正门。如果表名只可能是有限的几种直接查表放行最省心const TABLES { books: books, orders: orders, users: users } const table TABLES[userInput] if (!table) throw new Error(非法表名) db.query(SQLSELECT * FROM .append(table).append(SQL WHERE id ${id}))✅ 推荐优先级白名单 转义 拒绝用户输入。六、两个容易踩的坑 ⚠️性能陷阱官方 README 特别提醒——在循环里用不断变化的 raw 值执行大量预编译语句会快速撑爆预编译语句缓存prepared statement buffer性能不升反降。表名这类低频变化的场景问题不大但别把高频变量塞进 raw。raw 与占位符自由混用append()返回this可随意链式组合values顺序由 SQL 片段顺序自动维护不用再手动数$1、$2和参数数组。七、源码导航从哪读起项目文件很少半天能读完整个实现文件说明index.js核心SQLStatement类、SQL标签函数与append()实现index.d.tsTypeScript 类型定义test/unit.js单元测试覆盖sql/text/values生成与append()行为test/integration/mysql.js、test/integration/mysql2.js、test/integration/pg.js、test/integration/sequelize.js四大驱动的集成测试README.md官方文档「Raw values」一节是本文重点八、总结动态表名防注入三原则数据永远走占位符${value}自动变成?/$1交给驱动转义标识符走 raw 转义append(mysql.escapeId(x))或append(pg.escapeIdentifier(x))能白名单就白名单转义是兜底不是首选。掌握这套占位符 raw 值 escapeId的组合拳动态表名就不再是注入漏洞而是一段可控的 SQL 片段。【免费下载链接】node-sql-template-stringsES6 tagged template strings for prepared SQL statements 项目地址: https://gitcode.com/gh_mirrors/no/node-sql-template-strings创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表