如何在 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
库安全实现了 escape
和 unescape
方法。它们都使用 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'
您可以使用iconv
或iconv-lite
包从latin1 转换为utf-8 并获得正确的字符串。但是URL encoding 应该是 UTF-8。所以我认为忽略其他编码字符串并使用querystring.unescape
是安全的。
在 express 4.7.x 中,您可以将 query parser
配置设置为 simple
以使用内部使用 querystring.unescape
的 querystring.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 请求处理程序中编写非阻塞异步函数 [重复]