摘要:首先声明,这里所说的根域名,并不是指全球共有台根逻辑域名服务器这句话中的根域名。在本文中,我们将这样的域名称为根域名。无论访问哪个子站点,都要通过将存放到根域名下。在这种情况下,显然我们不能认为是根域名。比如一个名为的仓库。
首先声明,这里所说的“根域名”,并不是指“全球共有13台根逻辑域名服务器”这句话中的“根域名”。而是指某一个站点的“根域名”。
百度搜索是“www.baidu.com”,百度翻译的域名是“fanyi.baidu.com”,百度地图的域名则是“map.baidu.com”。这些域名有共同的部分“baidu.com”。在本文中,我们将“baidu.com”这样的域名称为“根域名”。前端同学应该都知道,在“.baidu.com”这一域下的 cookie 可以在其他子站点下拿到(当然,前提是端口号和协议都保持一致)。
最近开发的过程中遇上了一个小问题。无论访问哪个子站点,都要通过 js 将 cookie 存放到根域名下。
一开始比较大意,直接拿正则匹配。问题是忽略了这世界上还存在“www.xxx.edu.cn”这样的站点。在这种情况下,显然我们不能认为”edu.cn“是根域名。想在一个叫“edu.cn”的域下存 cookie?对不起,浏览器做不到。(这句话很重要。)
正则匹配是做不到了。搜索了一下,网上也没有什么特别好的解决方案。无非是枚举出国内常见的一些顶级域名,然后再进行处理,如下面这个 PHP 的例子:
但如何确保我们枚举出的例子一定是完全的无遗漏的呢?不完美,放弃。
PSL接着上 github 上去找例子。倒是发现了一些解决域名的工具。比如一个名为 psl 的仓库。
PSL 是 “Public Suffix List” 的缩写,这个“公共域名后缀列表”项目本来是供浏览器厂商使用的。可以访问官网,另外建议看看这篇《域名小知识:Public Suffix List》。
我搜索到的这个 psl 仓库正是基于 PSL、使用 js 来解析域名的。粗略看了下,存放域名的 json 文件有 108 KB。吓死了。
另一款叫做 parse-domain 的,光是生成的正则表达式文件就有 203 KB。
没办法,一个跑到浏览器上的前端脚本,本身不到 1500 行,为了一个判断引入上百 KB 的外部依赖,实在不划算。
于是只能自己另起炉灶,想想别的办法。
document.domain首先想到的是 document.domain。在一些需要跨域的场景中,可能会见到这货的身影。比如这篇文章 所描述的,“相同主域名不同子域名下的页面,可以设置 document.domain 让它们同域”。
经过测试发现,对于域名c.example.edu.cn下的页面,可以执行下面这句:
document.domain = "example.edu.cn";
而在 Chrome 下,下面这句则无法执行:
// DOMException document.domain = "edu.cn";
浏览器会抛出DOMException:
1 Uncaught DOMException: Failed to set the "domain" property on "Document": "edu.cn" is not a suffix of "c.example.edu.cn".
IE 也会报出“参数无效”的错误;Firefox 下同样会抛出错误:
NS_ERROR_DOM_BAD_DOCUMENT_DOMAIN: Illegal document.domain value
从报错信息可以看到, DOMException 是可以捕获到的。那就好办了。
将域名(或页面当前的 document.domain) split 成数据 ["x", "example", "edu", "cn"],从右向左逐次加上一个元素,每次将单词使用句点连接并赋值给 document.domain。如果 catch 到错误,则进行下一次操作。一旦赋值成功,即可 break 循环。
上代码:
const domain = document.domain; const list = domain.split("."); let len = list.length; let rootDomain = domain; while (len--) { try { document.domain = list.slice(len).join("."); rootDomain = document.domain; break; } catch (e) {} } // 还得恢复原值,避免产生副作用 document.domain = domain; console.log(rootDomain);
很好,经过简单测试,Chrome、IE 妥妥的。
然而 Firefox 挂了。挂在最后的还原阶段。也就是说,Firefox 允许修改 document.domain,但不允许修改成上一级之后,再回退到下一级。
此外(感谢老大),在 Safari 上测试发现,document.domain = "cn" 不会报错!什么鬼?请移步《Webkit下最无敌的跨大域方案》。
功亏一篑。心好累啊。
Cookie 救火最后想起前面提到的一句,“想在一个叫 edu.cn 的域下存 cookie?对不起,浏览器做不到。”
要不咱试试 cookie?动手!
道理同上,每次尝试在手动拼接的 domain 下面存 cookie,然后检查 cookie 是否保存成功。一旦成功,则 break 循环,并清除该 cookie。没有副作用,只是多操作几次 cookie。
换个思路,总算是解决了。
代码被我放在了 Github 上。顺手贴在这里:
var KEY = "__rT_dM__" + (+new Date()); var R = new RegExp("(^|;)s*" + KEY + "=1"); var Y1970 = (new Date(0)).toUTCString(); module.exports = function getRootDomain() { var domain = document.domain || location.hostname; var list = domain.split("."); var len = list.length; var temp = ""; var temp2 = ""; while (len--) { temp = list.slice(len).join("."); temp2 = KEY + "=1;domain=." + temp; // try to set cookie document.cookie = temp2; if (R.test(document.cookie)) { // clear document.cookie = temp2 + ";expires=" + Y1970; return temp; } } };
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/82707.html
摘要:,表单的两个常见属性为填写表单的人提供一个输入提示。可用于任何表单控件,表示这个域是必要的,如果不填,则无法提交表单。,表格,表格由行中的数据单元格组成,列隐含地定义在行中。,表格应用于表示表格数据,而不是建立页面布局。 1,如何设计一个页面 1) 先规划好web页面的结构,首先画出一个草图,然后创建一个略图,最后再写html2) 规划页面时,先设计大的块元素,再用内联元素...
摘要:幸运的是,采用任播技术架设镜像服务器可解决该问题,并使得实际运行的根域名服务器数量大大增加。截至年月,全球共有台根域名服务器在运行。 前记 从我开始学习前端我就一直在做着我的个人简历网站,使用GitHubpPages的预览功能进行预览,但是由于最近我的个人简历,不停的丰富,图片增多,而且将css和js文件用webpack打包后变成一个很大的问价,网页的加载速度就变的像龟速一样,所以我决...
阅读 2038·2021-11-08 13:22
阅读 2502·2021-09-04 16:40
阅读 1145·2021-09-03 10:29
阅读 1711·2019-08-30 15:44
阅读 2122·2019-08-30 11:13
阅读 2787·2019-08-29 17:07
阅读 1964·2019-08-29 14:22
阅读 1245·2019-08-26 14:00