sql字符串

本文介绍了如何在MySQL中使用SqlString库进行简单SQL查询的转义,包括转义查询值、查询标识符,以及如何通过format()方法生成格式化的安全查询,以防止SQL注入攻击。
摘要由CSDN通过智能技术生成

MySQL 的简单 SQL 转义和格式

安装

$ npm install sqlstring

用法

var SqlString = require('sqlstring');

转义查询值

注意:这些转义值的方法仅在 禁用NO_BACKSLASH_ESCAPES SQL 模式(这是 MySQL 服务器的默认状态)时才有效。

注意该库执行客户端转义,因为这是一个在客户端生成 SQL 字符串的库。诸如此类的函数的语法 SqlString.format可能看起来类似于准备好的语句,但事实并非如此,并且该模块的转义规则用于生成结果 SQL 字符串。转义输入的目的是避免 SQL 注入攻击。为了支持增强的支持SETIN格式化,该模块将根据传入的 JavaScript 值的形状进行转义,并且生成的转义字符串可能不止一个值。当提供结构化用户输入作为要转义的值时,应注意验证输入的形状以验证输出是否符合预期。

为了避免 SQL 注入攻击,在 SQL 查询中使用用户提供的任何数据之前,您应该始终转义该数据。您可以使用以下方法来执行此 SqlString.escape()操作:

var userId = 'some user provided value';
var sql    = 'SELECT * FROM users WHERE id = ' + SqlString.escape(userId);
console.log(sql); // SELECT * FROM users WHERE id = 'some user provided value'

或者,您可以使用?字符作为您想要转义的值的占位符,如下所示:

var userId = 1;
var sql    = SqlString.format('SELECT * FROM users WHERE id = ?', [userId]);
console.log(sql); // SELECT * FROM users WHERE id = 1

多个占位符按照传递的顺序映射到值。例如,在以下查询中fooequals abarequals bbazequalsc和 idwill be userId

var userId = 1;
var sql    = SqlString.format('UPDATE users SET foo = ?, bar = ?, baz = ? WHERE id = ?',
  ['a', 'b', 'c', userId]);
console.log(sql); // UPDATE users SET foo = 'a', bar = 'b', baz = 'c' WHERE id = 1

这看起来类似于 MySQL 中的准备语句,但它实际上只是SqlString.escape()在内部使用相同的方法。

注意这也与准备好的语句不同,因为所有语句?都被替换,甚至那些包含在注释和字符串中的语句。

不同的值类型的转义方式不同,具体方法如下:

  • 数字保持不变
  • 布尔值转换为true/false
  • 日期对象转换为'YYYY-mm-dd HH:ii:ss'字符串
  • 缓冲区转换为十六进制字符串,例如X'0fa5'
  • 字符串被安全转义
  • 数组变成列表,例如['a', 'b']变成'a', 'b'
  • 嵌套数组被变成分组列表(用于批量插入),例如[['a', 'b'], ['c', 'd']]变成('a', 'b'), ('c', 'd')
  • 具有toSqlString方法的对象将被.toSqlString()调用,并且返回值将用作原始 SQL。
  • key = 'val'对于对象上的每个可枚举属性,对象都会变成对。如果属性的值是一个函数,则跳过它;如果属性的值是一个对象,则对其调用 toString() 并使用返回值。
  • undefined/null转换为NULL
  • NaN/Infinity保持原样。 MySQL 不支持这些,尝试将它们作为值插入将触发 MySQL 错误,直到它们实现支持。

您可能已经注意到,这种转义允许您做如下巧妙的事情:

var post  = {id: 1, title: 'Hello MySQL'};
var sql = SqlString.format('INSERT INTO posts SET ?', post);
console.log(sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'

toSqlString方法允许您使用函数形成复杂的查询:

var CURRENT_TIMESTAMP = { toSqlString: function() { return 'CURRENT_TIMESTAMP()'; } };
var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]);
console.log(sql); // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42

要使用方法生成对象toSqlStringSqlString.raw()可以使用该方法。这将创建一个在占位符中使用时保持不变的对象? ,对于将函数用作动态值非常有用:

注意提供的字符串SqlString.raw()在使用时将跳过所有转义函数,因此在传递未经验证的输入时要小心。

var CURRENT_TIMESTAMP = SqlString.raw('CURRENT_TIMESTAMP()');
var sql = SqlString.format('UPDATE posts SET modified = ? WHERE id = ?', [CURRENT_TIMESTAMP, 42]);
console.log(sql); // UPDATE posts SET modified = CURRENT_TIMESTAMP() WHERE id = 42

如果你觉得需要自己转义查询,也可以直接使用转义函数:

var sql = 'SELECT * FROM posts WHERE title=' + SqlString.escape('Hello MySQL');
console.log(sql); // SELECT * FROM posts WHERE title='Hello MySQL'

转义查询标识符

如果您不能信任 SQL 标识符(数据库/表/列名称),因为它是由用户提供的,您应该SqlString.escapeId(identifier)像这样转义它:

var sorter = 'date';
var sql    = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId(sorter);
console.log(sql); // SELECT * FROM posts ORDER BY `date`

它还支持添加限定标识符。它将逃脱这两个部分。

var sorter = 'date';
var sql    = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId('posts.' + sorter);
console.log(sql); // SELECT * FROM posts ORDER BY `posts`.`date`

如果您不想将其.视为限定标识符,TP钱包下载则可以将第二个参数设置为 ,true以便将字符串保留为文字标识符:

var sorter = 'date.2';
var sql    = 'SELECT * FROM posts ORDER BY ' + SqlString.escapeId(sorter, true);
console.log(sql); // SELECT * FROM posts ORDER BY `date.2`

或者,您可以使用??字符作为您想要转义的标识符的占位符,如下所示:

var userId = 1;
var columns = ['username', 'email'];
var sql     = SqlString.format('SELECT ?? FROM ?? WHERE id = ?', [columns, 'users', userId]);
console.log(sql); // SELECT `username`, `email` FROM `users` WHERE id = 1

请注意,最后一个字符序列是实验性的,语法可能会改变

当您将对象传递给.escape()或 时.format().escapeId()用于避免对象键中的 SQL 注入。

格式化查询

您可以SqlString.format使用 id 和值的正确转义来准备具有多个插入点的查询。一个简单的例子如下:

var userId  = 1;
var inserts = ['users', 'id', userId];
var sql     = SqlString.format('SELECT * FROM ?? WHERE ?? = ?', inserts);
console.log(sql); // SELECT * FROM `users` WHERE `id` = 1

接下来,您将获得一个有效的转义查询,然后您可以将其安全地发送到数据库。如果您希望在实际将查询发送到数据库之前准备好查询,那么这非常有用。您还可以选择(但不是必需)传入stringifyObjecttimeZone,允许您提供将对象转换为字符串的自定义方法,以及特定于位置/时区的Date

这可以进一步与SqlString.raw()帮助程序结合以生成包含 MySQL 函数作为动态值的 SQL:

var userId = 1;
var data   = { email: 'foobar@example.com', modified: SqlString.raw('NOW()') };
var sql    = SqlString.format('UPDATE ?? SET ? WHERE `id` = ?', ['users', data, userId]);
console.log(sql); // UPDATE `users` SET `email` = 'foobar@example.com', `modified` = NOW() WHERE `id` = 1
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值