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

Posted

技术标签:

【中文标题】如何在 express 中处理非 UTF-8 编码的 url【英文标题】:How to deal with non UTF-8 encoded urls in express 【发布时间】: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 相同的转换?

牢记在心

    我们正在接收对这些编码错误的 URL 的请求,并且 有一种方法可以使用deprecated unescape javascript function 和 对它们进行解码

    对这些 URL 的大部分请求来自 Bing Bot,我们希望尽量减少对我们搜索排名的不利影响。

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

【问题讨论】:

【参考方案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'))

【讨论】:

以上是关于如何在 express 中处理非 UTF-8 编码的 url的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Express 请求处理程序中编写非阻塞异步函数 [重复]

如何在 Express 请求处理程序中编写非阻塞异步函数 [重复]

如何在 Express (Node.js) 中使用 URL 编码处理 HTTP 基本身份验证

使用非utf-8编码在Python中解析XML

ascii 转换为 utf-8

从任何编码强制字符串为 UTF-8