如何处理快递中的非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表示?
铭记在心
- 我们正在接收这些严重编码的URL和请求
- 有一种方法来解码他们使用不赞成的
unescape
JavaScript函数和 -
这些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
库已经安全地实现了escape
和unescape
方法。 他们都使用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,并使用iconv
或iconv-lite
包得到正确的string。 但是URL编码应该是UTF-8。 所以我认为可以忽略其他编码的string,只使用querystring.unescape
。
在express 4.7.x中,你可以设置query parser
configuration为simple
的使用querystring.parse
,它在内部使用querystring.unescape
。
app.set('query parser', 'simple') // or 'extended' to use 'qs' module