我们有一个节点js应用程序,我们最近从IIS 7上运行(通过IIS节点)转移到在Linux上运行(Elastic Beanstalk)。自从我们切换以来,我们已经将大量非UTF-8网址发送到我们的应用程序(主要来自爬虫),例如:
IIS正在转换为Bj%F6rk
的 Björk
。现在这被传递给我们的应用程序,我们的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字符串表示之前,是否有推荐的安全方式我们可以执行与IIS相同的转换?
铭记
unescape
javascript function和这些网址的大部分请求来自Bing Bot,我们希望尽量减少对搜索排名的不利影响。
unescape
在不久的将来被删除?答案 0 :(得分:10)
不,你不应该。正在进行的请求使用非UTF8 URI组件。这不应该是你的问题。我们真的应该为所有传入的网址执行此操作吗?
我们应该有任何安全或性能影响 关心?
URI组件的编码不是安全问题。通过查询字符串或路径参数进行注入尝试。但这是另一个主题。在性能方面,每个中间件都会让您的响应花费更长的时间。但我甚至不担心这一点。如果您想自己解码URI,那就去做吧。它只需要几毫秒。
我们是否应该关注在近处移除unescape 未来?
其实你应该。不推荐使用unescape
。如果你还想使用它;只是检查它是否存在。即'unescape' in global
。您还可以使用内置备用: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响应时它将被爬虫/机器人存储并且它将被传播。然后,您将不得不处理更多不良请求。
结束;不要通过unescape
进行解码。 Express已尝试通过适当的解码来解码:decodeURIComponent
。如果失败了,就让它成为。
答案 1 :(得分:1)
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'
您可以将latin1转换为utf-8,并使用iconv
或iconv-lite
包获取正确的字符串。但是URL encoding应该是UTF-8。因此,我认为忽略其他编码字符串并使用querystring.unescape
。
在express 4.7.x中,您可以将query parser
配置设置为simple
,以使用内部使用querystring.parse
的{{1}}。
querystring.unescape
答案 2 :(得分:0)
我推荐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'))