node mysql防止SQL注入转义查询值

2019-09-03139次阅读nodeMySQL

node mysql防止SQL注入转义查询值,注意:这些转义值的方法仅在禁用NO_BACKSLASH_ESCAPES SQL模式(这是MySQL服务器的默认状态)时有效。

为了避免SQL注入攻击,在SQL查询中使用任何用户提供的数据之前,都应该先对其进行转义。您可以使用mysql.escape(),connection.escape()或pool.escape()方法:

var userId = 'some user provided value';
var sql    = 'SELECT * FROM users WHERE id = ' + connection.escape(userId);
connection.query(sql, function (error, results, fields) {
  if (error) throw error;
  // ...
});

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

connection.query('SELECT * FROM users WHERE id = ?', [userId], function (error, results, fields) {
  if (error) throw error;
  // ...
});

多个占位符按照传递的顺序映射到与之对应的值。例如,在下面查询中,foo等于a,bar等于b,baz等于c,id将是userid:

connection.query('UPDATE users SET foo = ?, bar = ?, baz = ? WHERE id = ?', ['a', 'b', 'c', userId], function (error, results, fields) {
  if (error) throw error;
  // ...
});

这看起来类似于MySQL中的预处理语句,但是它实际上也是在内部使用相同的connection.escape()方法

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

  • 数字保持不变
  • 布尔值转换为true/false
  • 日期对象将转换为'YYYY-mm-dd HH:ii:ss'字符串
  • Buffers转换为十六进制字符串,例如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 query = connection.query('INSERT INTO posts SET ?', post, function (error, results, fields) {
  if (error) throw error;
  // Neat!
});
console.log(query.sql); // INSERT INTO posts SET `id` = 1, `title` = 'Hello MySQL'

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

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

要使toSqlString方法生成对象,可以使用mysql.raw()方法。这会创建一个在?占位符中使用时不会被触摸的对象,这对于将函数用作动态值非常有用。

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

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

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

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

转义查询标识符

如果您不能信任SQL标识符(数据库/表/列名称),因为它是由用户提供的,则应使用mysql.escapeid(标识符)、connection.escapeid(标识符)或pool.escapeid(标识符)对其进行转义,如下所示:

var sorter = 'date';
var sql    = 'SELECT * FROM posts ORDER BY ' + connection.escapeId(sorter);
connection.query(sql, function (error, results, fields) {
  if (error) throw error;
  // ...
});

它还支持添加限定标识符。它会从两部分转义。

var sorter = 'date';
var sql    = 'SELECT * FROM posts ORDER BY ' + connection.escapeId('posts.' + sorter);
// -> SELECT * FROM posts ORDER BY `posts`.`date`

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

var sorter = 'date.2';
var sql    = 'SELECT * FROM posts ORDER BY ' + connection.escapeId(sorter, true);
// -> SELECT * FROM posts ORDER BY `date.2`

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

var userId = 1;
var columns = ['username', 'email'];
var query = connection.query('SELECT ?? FROM ?? WHERE id = ?', [columns, 'users', userId], function (error, results, fields) {
  if (error) throw error;
  // ...
});
 
console.log(query.sql); // SELECT `username`, `email` FROM `users` WHERE id = 1

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

自定义格式

如果您希望使用其他类型的查询转义格式,则可以使用连接配置选项来定义自定义格式函数。如果要使用内置.escape()或任何其他连接函数,则可以访问连接对象。

下面是如何实现另一种格式的示例:

connection.config.queryFormat = function (query, values) {
  if (!values) return query;
  return query.replace(/\:(\w+)/g, function (txt, key) {
    if (values.hasOwnProperty(key)) {
      return this.escape(values[key]);
    }
    return txt;
  }.bind(this));
};
 
connection.query("UPDATE posts SET title = :title", { title: "Hello MySQL" });

 

上一篇: 使用pointer-events禁用事件触发  下一篇: CSS3 Animation属性大全  

node mysql防止SQL注入转义查询值相关文章