如何处理快递中的非UTF-8编码的url

我们有一个节点js应用程序,我们最近从IIS 7上运行(通过IIS节点)转移到在Linux(Elastic Beanstalk)上运行。 由于我们切换,我们已经得到了很多非UTF-8url被发送到我们的应用程序(主要来自抓取工具),例如:

Bj%F6rk IIS正在转换为Björk 。 这现在正在传递给我们的应用程序,我们的Web框架(快递)最终呼吁

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)

有没有推荐的安全的方式,我们可以执行相同的转换为IIS之前发送的urlstring表示?

铭记在心

  1. 我们正在接收这些严重编码的URL和请求
  2. 有一种方法来解码他们使用不赞成的unescape JavaScript函数和
  3. 这些url的大部分请求都来自Bing Bot,我们希望尽量减less对search排名的不利影响。

    • 我们真的应该为所有传入的url做这个吗?
    • 我们应该关注哪些安全或性能问题?
    • 我们是否应该担心在不久的将来会被删除?
    • 有没有更好/更安全的方法来解决这个问题(是的,我们读过的MDN文章链接到上面)

我们真的应该为所有传入的url做这个吗?

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

我们应该关注哪些安全或性能问题?

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

我们是否应该担心在不久的将来会被删除?

其实你应该。 unescape已被弃用。 如果你仍然想使用它; 只是检查它是否存在。 即'unescape' in global 。 你也可以使用内build的替代方法: require('querystring').unescape()在每种情况下都不会产生相同的结果,但不会抛出URIError 。 (虽然不build议)。

为了尽量减less对search排名的不利影响:

确定您的快递应用在这些情况下返回的状态码。 它可能是500 (内部服务器错误),看起来很糟糕, 404 (未find),这将告诉爬虫你没有查询的结果(这可能不是真的)。

在这些情况下,我build议你通过返回一个客户端错误(比如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响应时,它将被抓取者/机器人存储,并且会被传播。 那么你将不得不面对更多不好的要求。

得出结论 ; 不要通过unescape解码。 Express已经尝试通过正确的解码来解码: decodeURIComponent 。 如果失败了,就这样吧。

Node.js queryString库已经安全地实现了escapeunescape方法。 他们都使用utf-8编码。 unescape首先尝试decodeURIComponent ,如果失败,则尝试安全快速的替代实现 。

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

但是你有拉丁-1编码的string( %F6而不是%C3%B6 ),所以querystring.unescape会给人意想不到的结果,但它不会破坏你的代码:

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

你可能能够从latin1转换为utf-8,并使用iconviconv-lite包得到正确的string。 但是URL编码应该是UTF-8。 所以我认为可以忽略其他编码的string,只使用querystring.unescape


在express 4.7.x中,你可以设置query parserconfiguration为simple的使用querystring.parse ,它在内部使用querystring.unescape

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