计算机基础:域名以及跨域
域名基础知识:
一个完整的域名由二个或二个以上部分组成,各部分之间用英文的句号"."来分隔,最后一个"."的右边部分称为*域名(TLD,也称为一级域名),最后一个"."的左边部分称为二级域名(SLD),二级域名的左边部分称为三级域名,以此类推,每一级的域名控制它下一级域名的分配。定义是这样的,在域名中包含两个点的,就叫二级域名,只包含一个点的,就是一级域名。
域名级数是指一个域名由多少级组成,域名的各个级别被“.”分开,简而言之,有多少个点就是几级域名。
*域名在开头有一个点,一级域名就是在“com net org”前加一级:http://www.cdxwcx.com/(前面是www的通用网址)
二级域名就是在一级域名前再加一级:http://domain.cdxwcx.com/(www替换成了别的)
二级域名及其以上级别的域名,统称为子域名,不在“注册域名”的范畴中。
中间由点号分隔开,最右边的那个词称为*域名。
(!补充: 也就是说www只是一个主机名,真正的一级域名是由一个合法字符串+域名后缀组成。)
一级域名又叫*域名,就像我们现在的网站建设网站网址 http://cdxwcx.com/ 是一级域名 如果http://domain.cdxwcx.com/ 就是二级域名了。
四种跨域方法:
1. JSONP
首先要介绍的跨域方法必然是 JSONP。
现在你想要获取其他网站上的 JavaScript 脚本,你非常高兴的使用 XMLHttpRequest 对象来获取。但是浏览器一点儿也不配合你,无情的弹出了下面的错误信息:
XMLHttpRequest cannot load http://x.com/main.dat. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://y.com' is therefore not allowed access.
为了避免这种蛋疼的事情发生,JSONP 就派上用场了。你心里肯定会想,我难道要用后台做个爬虫来获取这个数据吗?!
<script> 标签是不受同源策略的限制的,它可以载入任意地方的 JavaScript 文件,而并不要求同源。
所以 JSONP 的理念就是,我和服务端约定好一个函数名,当我请求文件的时候,服务端返回一段 JavaScript。这段 JavaScript 调用了我们约定好的函数,并且将数据当做参数传入。
非常巧合的一点(其实并不是),JSON 的数据格式和 JavaScript 语言里对象的格式正好相同。所以在我们约定的函数里面可以直接使用这个对象。
你需要获取数据的页面 index.html:
<script>
function getWeather(data) {
console.log(data);
}
</script>
<script src="http://x.y.com/xx.js">
http://x.y.com/xx.js 文件内容:
JavaScript
getWeather({
"城市": "北京",
"天气": "大雾"
});
我们可以看到,在我们定义了 getWeather(data) 这个函数后,直接载入了 xx.js。
在这个脚本中,执行了 getWeather 函数,并传入了一个对象。然后我们在这个函数中将这个对象输出到 console 中。
这就是整个 JSONP 的流程。
2. document.domain
使用条件:
- 有其他页面 window 对象的引用。
- 二级域名相同。
- 协议相同。
- 端口相同。
document.domain 默认的值是整个域名,所以即使两个域名的二级域名一样,那么他们的document.domain 也不一样。
使用方法就是将符合上述条件页面的 document.domain 设置为同样的二级域名。这样我们就可以使用其他页面的 window 对象引用做我们想做的任何事情了。
补充知识:
- x.one.example.com 和 y.one.example.com 可以将 document.domain 设置为 one.example.com,也可以设置为 example.com。
- document.domain 只能设置为当前域名的一个后缀,并且包括二级域名或以上(.edu.cn 这种整个算*域名)。
我们直接操刀演示,用两个网站 http://wenku.baidu.com/ 和 http://zhidao.baidu.com/。
这两个网站都是 http 协议,端口都是 80, 且二级域名都是 baidu.com。
打开 http://wenku.baidu.com/,在 console 中输入代码:
JavaScript
document.domain = 'baidu.com';
var otherWindow = window.open('http://zhidao.baidu.com/');
我们现在已经发现百度知道的网页已经打开了,在百度知道网页的 console 中输入以下代码:
JavaScript
document.domain = 'baidu.com';
现在回到百度文库的网页,我们就可以使用百度知道网页的 window 对象来操作百度知道的网页了。例如:
JavaScript
var divs = otherWindow.document.getElementsByTagName('div');
上面这个例子的使用方法并不常见,但是非常详细的说明了这种方法的原理。
这种方法主要用在控制 <iframe> 的情况中。
比如我的页面(http://one.example.com/index.html)中内嵌了一个 <iframe> :
<iframe id="iframe" src="http://two.example.com/iframe.html"></iframe>
我们在 iframe.html 中使用 JavaScript 将 document.domain 设置好,也就是 example.com。
在 index.html 执行以下脚本:
JavaScript
var iframe = document.getElementById('iframe');
document.domain = 'example.com';
iframe.contentDocument; // 框架的 document 对象
iframe.contentWindow; // 框架的 window 对象
这样,我们就可以获得对框架的完全控制权了。
补充知识(绝对干货):
当两个页面不做任何处理,但是使用了框架或者 window.open() 得到了某个页面的 window 对象的引用,我们可以直接访问的属性有哪些?
方法 |
window.blur |
window.close |
window.focus |
window.postMessage |
window.location.replace |
属性 |
权限 |
window.closed |
只读 |
window.frames |
只读 |
window.length |
只读 |
window.location.href |
只写 |
window.opener |
只读 |
window.parent |
只读 |
window.self |
只读 |
window.top |
只读 |
window.window |
只读 |
3. window.name
我们来看以下一个场景:
随意打开一个页面,输入以下代码:
JavaScript
dow.name = "My window's name";
location.href = "http://www.qq.com/";
再检测 window.name :
JavaScript
window.name; // My window's name
可以看到,如果在一个标签里面跳转网页的话,我们的 window.name 是不会改变的。
基于这个思想,我们可以在某个页面设置好 window.name 的值,然后跳转到另外一个页面。在这个页面中就可以获取到我们刚刚设置的 了。
由于安全原因,浏览器始终会保持 window.name 是 string 类型。
这个方法也可以应用到与 <iframe> 的交互上来。
我的页面(http://one.example.com/index.html)中内嵌了一个 <iframe> :
<iframe id="iframe" src="http://omg.com/iframe.html"></iframe>
在 iframe.html 中设置好了 window.name 为我们要传递的字符串。
我们在 index.html 中写了下面的代码:
JavaScript
var iframe = document.getElementById('iframe');
var data = '';
iframe.onload = function() {
data = iframe.contentWindow.name;
};
定睛一看,为毛线报错?
细心的读者们肯定已经发现了,两个页面完全不同源啊!
由于 window.name 不随着 URL 的跳转而改变,所以我们使用一个暗黑技术来解决这个问题:
JavaScript
var iframe = document.getElementById('iframe');
var data = '';
iframe.onload = function() {
iframe.onload = function(){
data = iframe.contentWindow.name;
}
iframe.src = 'about:blank';
};
或者将里面的 about:blank 替换成某个同源页面(最好是空页面,减少加载时间)。
补充知识:
about:blank , javascript: 和 data: 中的内容,继承了载入他们的页面的源。
这种方法与 document.domain 方法相比,放宽了域名后缀要相同的限制,可以从任意页面获取 string 类型的数据。
4. [HTML5] postMessage
在 HTML5 中, window 对象增加了一个非常有用的方法:
JavaScript
windowObj.postMessage(message, targetOrigin);
- windowObj : 接受消息的 Window 对象。
- message : 在最新的浏览器中可以是对象。
- targetOrigin : 目标的源,* 表示任意。
这个方法非常强大,无视协议,端口,域名的不同。下面是烤熟的栗子:
JavaScript
var windowObj = window; // 可以是其他的 Window 对象的引用
var data = null;
addEventListener('message', function(e){
if(e.origin == 'http://jasonkid.github.io/fezone') {
data = e.data;
e.source.postMessage('Got it!', '*');
}
});
message 事件就是用来接收 postMessage 发送过来的请求的。函数参数的属性有以下几个:
- origin : 发送消息的 window 的源。
- data : 数据。
- source : 发送消息的 Window 对象。
上一篇: Android采用双缓冲技术实现画板
推荐阅读
-
计算机基础:域名以及跨域
-
vue-cli3跨域处理,解决500错误以及Proxy error
-
请问这是不是跨域问题?以及我的转发处理方案科学吗?会不会有坑?为何大家会嘲讽这个方案?
-
angularjs 控制器不能访问nodejs 3000端口,跨域访问 博客分类: angularjsjs基础node
-
angularjs 控制器不能访问nodejs 3000端口,跨域访问 博客分类: angularjsjs基础node
-
Yii2实现多域名跨域同步登录退出
-
ajax跨域(基础域名相同)表单提交的方法
-
php中cookie跨域的解决方案以及IE和safari浏览器中的坑
-
AJAX机制详解以及跨域通信
-
ajax跨域(基础域名相同)表单提交的方法