【问题标题】:How to deal with non UTF-8 encoded urls in express如何在 express 中处理非 UTF-8 编码的 url
【发布时间】:2015-09-18 13:22:56
【问题描述】:

我们有一个 node js 应用程序,我们最近从在 IIS 7 上运行(通过 IIS 节点)转移到在 Linux 上运行(Elastic Beanstalk)。自从我们切换后,我们收到了很多非 UTF-8 url 被发送到我们的应用程序(主要来自爬虫),例如:

Bj%F6rk IIS 将其转换为 Björk。这现在被传递给我们的应用程序,我们的网络框架(express)最终调用到

decodeURIComponent('Bj%F6rk'); URIError: URI malformed at decodeURIComponent (native) at repl:1:1 at REPLServer.self.eval (repl.js:110:21) at repl.js:249:20 at REPLServer.self.eval (repl.js:122:7) at Interface.<anonymous> (repl.js:239:12) at Interface.emit (events.js:95:17) at Interface._onLine (readline.js:203:10) at Interface._line (readline.js:532:8) at Interface._ttyWrite (readline.js:761:14)

有没有推荐的安全方法,我们可以在将 url 字符串发送到 express 之前执行与 IIS 相同的转换?

牢记在心

  1. 我们正在接收对这些编码错误的 URL 的请求,并且
  2. 有一种方法可以使用deprecated unescape javascript function
  3. 对它们进行解码
  4. 对这些 URL 的大部分请求来自 Bing Bot,我们希望尽量减少对我们搜索排名的不利影响。

    • 我们真的应该对所有传入的 URL 都这样做吗?
    • 我们是否应该关注任何安全或性能影响?
    • 我们应该担心unescape 在不久的将来会被删除吗?
    • 有没有更好/更安全的方法来解决这个问题(是的,我们确实阅读了上面链接的 MDN 文章)

【问题讨论】:

    标签: javascript node.js iis url-encoding bing


    【解决方案1】:

    我们真的应该对所有传入的 URL 都这样做吗?

    不,你不应该。发出的请求使用非 UTF8 URI 组件。这不应该是你的问题。

    是否存在我们应该考虑的任何安全或性能影响 关心?

    URI 组件的编码不是安全问题。通过查询字符串或路径参数的注入尝试是。但那是另一个话题。在性能方面,每个中间件都会使您的响应时间更长一些。但我什至不会担心这个。如果你想自己解码 URI,那就去做吧。只需几毫秒。

    我们是否应该担心 unescape 在附近被移除 未来?

    其实你应该。 unescape 已弃用。如果您还想使用它;只需先检查它是否存在。即'unescape' in global。您还可以使用内置的备用:require('querystring').unescape(),它不会在每种情况下产生相同的结果,但不会抛出 URIError。 (虽然不推荐)。

    为了尽量减少对搜索排名的不利影响:

    确定您的快速应用在这些情况下返回的状态代码。可能是 500 (INTERNAL SERVER ERROR) 看起来很糟糕,而 404 (NOT FOUND) 会告诉爬虫您没有查询结果(可能不是真的)。

    在这些情况下,我建议您通过返回诸如 400 (BAD REQUEST) 之类的客户端错误来覆盖它,因为问题的根源是请求的格式错误的 URI 组件,应该是在 UTF-8 中,但不是。爬虫/机器人应该关注这一点。

    // middleware for responding with BAD REQUEST
    app.use(function (err, req, res, next) {
        if (err instanceof URIError) {
            res.status(400).send();
        }
    });
    

    首先,尝试为格式错误的 URI 返回结果还有其他副作用。首先,您将允许一个错误的请求 - 不可能是好的 :)。其次,这意味着您有一个错误 URI 的结果,当爬虫/机器人收到 200 OK 响应时,该 URI 将被存储并传播。然后你将不得不处理更多的错误请求。

    总结;不要通过unescape 解码。 Express 已经尝试通过正确的方式进行解码:decodeURIComponent。如果失败了,那就顺其自然吧。

    【讨论】:

    • 这符合我们的想法,也是我们将继续前进的方向。感谢您对问题的详细回答。享受你的赏金,不要一次吃掉它! :)
    【解决方案2】:

    Node.js queryString 库安全实现了 escapeunescape 方法。它们都使用 utf-8 编码。 unescape 首先尝试 decodeURIComponent,当失败时,它会尝试使用 safe fast alternative implementation

    > querystring.escape('ö')
    '%C3%B6'
    > querystring.unescape('%C3%B6')
    'ö'
    

    但是你有 latin-1 编码字符串(%F6 而不是 %C3%B6 ),所以 querystring.unescape 会给出意想不到的结果,但它不会破坏你的代码:

    > querystring.unescape('Bj%F6rk')
    'Bj�rk'
    

    您可以使用iconviconv-lite 包从latin1 转换为utf-8 并获得正确的字符串。但是URL encoding 应该是 UTF-8。所以我认为忽略其他编码字符串并使用querystring.unescape是安全的。


    在 express 4.7.x 中,您可以将 query parser 配置设置为 simple 以使用内部使用 querystring.unescapequerystring.parse

    app.set('query parser', 'simple') // or 'extended' to use 'qs' module
    

    【讨论】:

      【解决方案3】:

      我推荐 Nodejs decode-uri-charset,https://www.npmjs.com/package/decode-uri-charset

      var url_decode = require('decode-uri-charset');
      console.log(url_decode('%C7%CF%C0%CC', 'euc-kr'))
      

      【讨论】:

        猜你喜欢
        • 2010-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多