如何在express中处理非UTF-8编码的url

How to deal with non UTF-8 encoded urls in express

本文关键字:UTF-8 编码 url 处理 express      更新时间:2023-09-26

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

IIS正在转换为CCD_ 2的CCD_。这现在正在传递给我们的应用程序,我们的web框架(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. 我们收到了对这些编码错误的URLS的请求
  2. 有一种方法可以使用不推荐使用的unescape javascript函数对它们进行解码
  3. 对这些URL的大多数请求都来自Bing Bot,我们希望尽量减少对搜索排名的不利影响。

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

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

不,你不应该。正在进行的请求使用非UTF8 URI组件。这不应该是你的问题。

我们是否应该受到任何安全或性能影响关心

URI组件的编码不是安全问题。通过querystring或路径参数的注入尝试为。但这是另一个主题。就性能而言,每个中间件都会使您的响应花费更长的时间。但我甚至不会担心。如果你想自己解码URI,只需要几毫秒。

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

实际上你应该。unescape已弃用。如果你仍然想使用它;只要先检查一下它是否存在。即CCD_ 7。您还可以使用内置的备用:require('querystring').unescape(),它不会在所有情况下都产生相同的结果,但不会抛出URIError。(但不推荐(。

为了最大限度地减少对搜索排名的不利影响:

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

在这些情况下,我建议您通过返回客户端错误来覆盖这一点,例如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的响应时,它会被存储,并被传播。然后你将不得不处理更多的坏请求。

结束;不通过Bj%F6rk0进行解码。Express已经尝试通过正确的方式进行解码:decodeURIComponent。如果失败,那就顺其自然。

Node.js queryString库具有escapeunescape方法的安全实现。它们都使用utf-8编码。unescape首先尝试decodeURIComponent,失败时尝试安全快速的替代实现。

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

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

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

您可能能够使用Björk0或iconv-lite包将latin1转换为utf-8并获得正确的字符串。但是URL编码应该是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

我建议Nodejs解码uri字符集,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'))