使 javascript 字符串 sql 友好

Posted

技术标签:

【中文标题】使 javascript 字符串 sql 友好【英文标题】:Making a javascript string sql friendly 【发布时间】:2011-12-06 09:24:19 【问题描述】:

有没有办法让传递给 NodeJS 的 javascript 字符串对 mysql 友好?我正在尝试将电子邮件地址传递给我的 NodeJS 服务器并查询 MySQL 数据库。在处理诸如用户名之类的常规文本时效果很好,但电子邮件地址却不行。显然使用转义不是正确的答案,因为它不适用于 SQL 插入。我假设我需要 php 函数 mysql_real_escape_string() 的行。

【问题讨论】:

你需要一些类似于清理输入的东西,然后是一些类似于适当的 mysql 库的东西,它允许你将键/值对传递给插入函数 我正在使用运行良好的 NodeJS MySQL 库。我该如何正确消毒它? 在其上运行电子邮件正则表达式,如果失败则将错误消息发送回客户端。 @Raynos 这适用于电子邮件,因为 RFC2822 不允许出现很多奇怪的字符,但最好有一个所有字符串的验证器。 @Bobby,你姓 Tables 吗? 【参考方案1】:

事实证明 mysql_real_escape_string() 非常简单。 According to the documentation:

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's recommendations 一样(与 PHP 原版不同)。

我确实知道mysql_real_escape_string() 可以识别字符集,但我不确定这会带来什么好处。

over here 对这些问题进行了很好的讨论。

【讨论】:

@Bobby 好吧,我和你一样惊讶!我只是希望它在所有情况下都是安全的:-) @Bobby 不要忘记可以触发错误的表情符号。可以添加 var m=m.replace(/([\uE000-\uF8FF]|\uD83C[\uDF00-\uDFFF]|\uD83D[\uDC00-\uDDFF])/g, ''); 之类的内容 @zipp 你有关于这个问题的更多细节吗?如果您有此权限,请随时编辑我的答案。 @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(); 你可以阅读更多关于表情符号问题here 的信息。正如@Soyoes 所说,基本上你需要 utf8mb4。 @Pauld'Aoust,这太棒了。谢谢你。为我节省了大量时间。一个小故障完全阻碍了我的主要任务。【参考方案2】:

也适用于前端项目的解决方案

安装sqlstring(由mysqljs维护的库):

npm install sqlstring --save-dev  

如果你使用 TypeScript,你也可以安装类型:

npm install @types/sqlstring --save-dev  

然后使用它:

import  escape  from 'sqlstring';

const escapedString = escape(`it's going to be escaped!`);

【讨论】:

这应该是公认的答案。使用 sqlString 包太容易了【参考方案3】:

为什么不简单地使用内置函数escape 像这样:

var escaped_str = escape(your_unescaped_string);

这适用于我在后端使用 MySQL。

【讨论】:

因为该功能已被弃用。【参考方案4】:

对于从 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 ); 

【讨论】:

【参考方案5】:

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

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
        
    );

【讨论】:

这是对已接受答案的一个非常好的补充。谢谢。【参考方案6】:

使用数组代替 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 语句更直接的方法。我怀疑它也比我的效率更高,但是我当然没有做过比较来看看。感谢您提供替代方法! 在不得不另辟蹊径的情况下交换两者更容易,而不必编写另一组 case 语句。在我看来,它也更实用,更符合 Javascript 的精神。很可能会得到很大的改进。【参考方案7】:

如果有人在寻找,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的摘录。

【讨论】:

【参考方案8】:

如果你玩的是CJK字符http://en.wikipedia.org/wiki/CJK_characters或者ios/android/其他手机的一些特殊的情感图标...比如“�‡‰™©?”或者decodeURIComponent("\xF3\xBE\xAD\xA0 ")。

你需要像这样设置你的 my.cnf

[client]
default-character-set = utf8mb4

[mysqld]
character-set-server = utf8mb4
skip-character-set-client-handshake

【讨论】:

以上是关于使 javascript 字符串 sql 友好的主要内容,如果未能解决你的问题,请参考以下文章

如何使 C++ 类 gdb 友好?

使字符串 URL 友好(例如:将蒙特利尔转换为蒙特利尔)

.htaccess 使 url 对搜索引擎友好

通过 Selenium 和 Python 和 JavaScript 使 WebElement 可见

使 PHP 脚本完全 Unicode 友好的声明

如何使用 jquery ui 自动完成使匹配的文本变为粗体?