使 javascript 字符串 sql 友好

IT技术 javascript sql string node.js escaping
2021-02-10 00:20:41

是否可以将 javascript 字符串传递给 NodeJS 对 MySQL 友好?我正在尝试将电子邮件地址传递给我的 NodeJS 服务器并查询 MySQL 数据库。在执行常规文本(例如用户名)时可以正常工作,但电子邮件地址不行。使用转义显然不是正确的答案,因为它不适用于 SQL 插入。我假设我需要一些关于 PHP 函数的内容mysql_real_escape_string()

6个回答

事实证明 mysql_real_escape_string() 非常简单。根据文档

mysql_real_escape_string()调用 MySQL 的库函数 mysql_real_escape_string,它在以下字符前加上反斜杠:\x00、\n、\r、\、'、" 和 \x1a。

听起来很简单,实际上。你可以这样做:

function mysql_real_escape_string (str) {
    return str.replace(/[\0\x08\x09\x1a\n\r"'\\\%]/g, function (char) {
        switch (char) {
            case "\0":
                return "\\0";
            case "\x08":
                return "\\b";
            case "\x09":
                return "\\t";
            case "\x1a":
                return "\\z";
            case "\n":
                return "\\n";
            case "\r":
                return "\\r";
            case "\"":
            case "'":
            case "\\":
            case "%":
                return "\\"+char; // prepends a backslash to backslash, percent,
                                  // and double/single quotes
            default:
                return char;
        }
    });
}

注意:我没有通过任何类型的单元测试或安全测试运行它,但它似乎确实有效——而且,作为一个额外的好处,它转义了制表符、退格符和“%”,因此它也可以使用在 LIKE 查询中,根据OWASP 的建议(与 PHP 原始版本不同)。

我确实知道这mysql_real_escape_string()是字符集感知的,但我不确定这会带来什么好处。

此处对这些问题进行很好的讨论

@Bobby 不要忘记可能引发错误的表情符号。var m=m.replace(/([\uE000-\uF8FF]|\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDDFF])/g, ''); 可以添加类似的东西
2021-03-16 00:20:41
@Pauld'Aoust 好吧,我在解析表情符号时遇到了一些问题。这需要编辑配置。但是,我做不到。我最终只调用了这两个函数,我确信它们可以合二为一:posts[i].message = mysql_real_escape_string(posts[i].message); posts[i].message = posts[i].message.replace(/([\uE000-\uF8FF]|\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDDFF])/g, '').trim();您可以在此处阅读有关表情符号问题的更多信息基本上你需要 utf8mb4 正如@Soyoes 所说。
2021-03-24 00:20:41
@Pauld'Aoust,太棒了。谢谢你。为我节省了大量时间。一个小故障完全阻碍了我的主要任务。
2021-03-25 00:20:41
@Bobby 好吧,我和你一样惊讶!我只是希望它在所有情况下都是安全的:-)
2021-04-03 00:20:41
@zipp 你有关于这个问题的更多细节吗?如果您有此特权,请随时编辑我的答案。
2021-04-14 00:20:41

了解到将数字传递给此函数会导致它所使用的整个过程安静地死亡的艰难方法。所以我添加了一个小测试:

function mysql_real_escape_string (str) {
    if (typeof str != 'string')
        return str;

    return str.replace(/[\0\x08\x09\x1a\n\r"'\\\%]/g, function (char) {
        switch (char) {
            case "\0":
                return "\\0";
            case "\x08":
                return "\\b";
            case "\x09":
                return "\\t";
            case "\x1a":
                return "\\z";
            case "\n":
                return "\\n";
            case "\r":
                return "\\r";
            case "\"":
            case "'":
            case "\\":
            case "%":
                return "\\"+char; // prepends a backslash to backslash, percent,
                                  // and double/single quotes
        }
    });
}
这是对已接受答案的一个很好的补充。谢谢。
2021-03-19 00:20:41

对于从 2018 年开始使用此答案的任何人,还值得注意的是,许多 javascript 数据库框架现在都包含 connection.escape 方法。

例如:

var mysql = require('mysql')

var connection = mysql.createConnection( // your connection string here 

var query = "SELECT THING FROM THING WHERE FRED= " + connection.escape( your_string_here ); 

如果有人正在寻找,CUBRID RDBMS 中的 escapeString()工作如下:

var _escapeString = function (val) {
  val = val.replace(/[\0\n\r\b\t\\'"\x1a]/g, function (s) {
    switch (s) {
      case "\0":
        return "\\0";
      case "\n":
        return "\\n";
      case "\r":
        return "\\r";
      case "\b":
        return "\\b";
      case "\t":
        return "\\t";
      case "\x1a":
        return "\\Z";
      case "'":
        return "''";
      case '"':
        return '""';
      default:
        return "\\" + s;
    }
  });

  return val;
};

这是CUBRID Node.js driver的摘录

使用数组而不是 case 语句:

var regex = new RegExp(/[\0\x08\x09\x1a\n\r"'\\\%]/g)
var escaper = function escaper(char){
    var m = ['\\0', '\\x08', '\\x09', '\\x1a', '\\n', '\\r', "'", '"', "\\", '\\\\', "%"];
    var r = ['\\\\0', '\\\\b', '\\\\t', '\\\\z', '\\\\n', '\\\\r', "''", '""', '\\\\', '\\\\\\\\', '\\%'];
    return r[m.indexOf(char)];
};

//Implementation
"Some Crazy String that Needs Escaping".replace(regex, escaper);
我认为有一些比我的答案中的 switch 语句更直接的方法。我怀疑它也比我的更有效率,但当然我还没有做过比较。感谢您提供替代方法!
2021-03-18 00:20:41
如果不得不走另一条路,而不必编写另一组 case 语句,则更容易交换两者。在我看来,它也更实用,更符合 Javascript 的精神。很可能可以大大改进。
2021-03-26 00:20:41