我正在开发西里尔文域上的网络应用程序。当前,该域托管一个“寄存页面”,表示该站点正在建设中。如果我在Chrome中访问它,我会在地址栏中看到punycode。 Safari会对其进行解码。出于开发目的,我修改了我的/etc/hosts
文件,使其能够通过测试西里尔域访问localhost。但是,Chrome和Safari均无法解码主机名。
我已经查询了此问题,但找不到任何明智的解决方案。 Node.js有一个名为punycode
的模块。现在,如果我的req.url
包含西里尔字符,它将得到URIComponent
编码,因此我编写了一个中间件对其进行解码:
app.use(function(req, res, next) {
var url = req.url,
decoded = decodeURIComponent(url);
if (url !== decoded) req.url = decoded;
next();
});
效果很好,我现在可以使用西里尔路由。但是,当我尝试将此逻辑应用于主机名时,它不起作用:
app.use(function(req, res, next) {
var hostname = req.hostname,
decoded = punycode.toUnicode(hostname);
if (hostname !== decoded) req.hostname = decoded;
// I have also tried return res.redirect('https://' + decoded + ':' + ...);
next();
});
很感谢任何形式的帮助。谢谢!
最佳答案
好的,所以经过研究,我发现这几乎是不可能的。主机解析策略严格地针对浏览器,并且存在(针对IDN)以防止危险的网络钓鱼活动。 Safari一方面将IDN从punycode解析为UTF-8字符串,另一方面Chrome则无法。
这些有害的网络钓鱼活动可能是由包含非ASCII字符的域引起的。考虑一组ASCII字母“ o,e,a”和UTF-8俄语(西里尔字母)字母“о,е,а”。它们看起来几乎相同,因此对于客户来说是无法区分的。因此,黑客可能会注册一个看起来像众所周知的域(使用ASCII“ a”的“ paypal.com”和使用UTF-8西里尔字母“а”的“pаypаl.com”)注册。
为了防止此类恶意活动,Chrome浏览器会将非ASCII字符编码为punycode(“pаypаl.com”的UTF-8西里尔字母“а”在浏览器地址栏中看起来像“ xn--pypl-53dc.com”,以警告客户端这不是原始网站)。
遗憾的是,到目前为止,IDN似乎并不是最佳解决方案。