我正在开发西里尔文域上的网络应用程序。当前,该域托管一个“寄存页面”,表示该站点正在建设中。如果我在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似乎并不是最佳解决方案。

07-24 17:51