本文主要是介绍计算机基础之域名,跨域,防盗链,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目录
1 域名基础
1.1 基本定义
1.2 主域名附加域名子域名
2 跨域访问原理和防盗链
2.1 防盗链
2.2 跨域访问原理
2.2.1 JSONP跨域原理
2.2.2 CORS跨域原理
2.3 同源策略
2.3.1 什么是同源策略
2.3.2 CORS
2.3.3 简单请求
2.3.4 预检请求
2.3.5 附带身份凭证的请求与通配符
2.3.6 完整的请求流程图
2.3.7 总结
3 四种跨域方法
3.1 JSONP
3.2 document.domain
3.3 window.name
3.4 [HTML5]postMessage
1 域名基础
1.1 基本定义
一个完整的域名由二个或二个以上部分组成,各部分之间用英文的句号"."来分隔,最后一个"."的右边部分称为顶级域名(TLD,也称为一级域名),最后一个"."的左边部分称为二级域名(SLD),二级域名的左边部分称为三级域名,以此类推,每一级的域名控制它下一级域名的分配。定义是这样的,在域名中包含两个点的,就叫二级域名,只包含一个点的,就是一级域名。
域名级数是指一个域名由多少级组成,域名的各个级别被“.”分开,简而言之,有多少个点就是几级域名。
顶级域名在开头有一个点,一级域名就是在“com net org”前加一级:http://www.cdxwcx.com/(前面是www的通用网址)
二级域名就是在一级域名前再加一级:http://domain.cdxwcx.com/(www替换成了别的)
二级域名及其以上级别的域名,统称为子域名,不在“注册域名”的范畴中。
中间由点号分隔开,最右边的那个词称为顶级域名。(!补充: 也就是说www只是一个主机名,真正的一级域名是由一个合法字符串+域名后缀组成。)
1.2 主域名附加域名子域名
主域名maindomain,也就是虚拟主机的帐号。主域名对应的ftp路径是 /public_html/
比如www.maindomain.com是主域名,你把一个名为aaa.php的网页上传到public_html下面,就可以用http://www.maindomain.com/aaa.php来访问了。
附加域,也就是国内说的“绑定域名”。除了主域名以外,还可以自由绑定无数个域名。附加域可以在 /public_html/**/ 下面自定义目录。
比如www.a.com是一个附加域,可以绑定到public_html/a.com下面,可以是public_html/a/ ,可以是public_html/mysite/a/ ,还可以public_html/本身,或者 /public_html/*/ 其中的*,可以自定义*
按照使用习惯,一般建议如下目录,这样看起来比较直观。只是建议,可以自定义。
www.maindomain.com 对应 /public_html/
www.a.com 对应 /public_html/a.com/
www.b.com 对应 /public_html/b.com/
www.c.com 对应 /public_html/c.com/
子域名,就是subdomain, 子域名,也可以自定义路径。
比如 bbs.maindomain.com 可以绑定到 /public_html/bbs.maindomain.com/ 目录,或者/public_html/bbs/
2 跨域访问原理和防盗链
2.1 防盗链
网站资源都有域的概念,浏览器加载一个站点时,首先加载这个站点的首页,一般是index.html或者index.php等。页面加载,如果仅仅是加载一个index.html页面,那么该页面里面只有文本,最终浏览器只能呈现一个文本页面。丰富的多媒体信息无法在站点上面展现。
那么我们看到的各类元素丰富的网页是如何在浏览器端生成并呈现的?其实,index.html在被解析时,浏览器会识别页面源码中的img,script等标签,标签内部一般会有src属性,src属性一般是一个绝对的URL地址或者相对本域的地址。浏览器会识别各种情况,并最终得到该资源的唯一地址,加载该资源。具体的加载过程就是对该资源的URL发起一个获取数据的请求,也就是GET请求。各种丰富的资源组成整个页面,浏览器按照html语法指定的格式排列获取到各类资源,最终呈现一个完整的页面。因此一个网页是由很多次请求,获取众多资源形成的,整个浏览器在一次网页呈现中会有很多次GET请求获取各个标签下的src资源。
上图是一个网页呈现过程中的抓包截图。可以看到,大量的加载css、js和图片类资源的get请求。
观察其中的请求目的地址,可以发现有两类,一个是本站的43.242段的IP地址,这是本站的空间地址,即向本站自身请求资源,一般来说这个是必须的,访问资源由自身托管。另外一类是访问182的网段拉取数据。这类数据不是托管站内的,是在其他站点的。浏览器在页面呈现的过程,拉取非本站的资源,这就称“盗链”
准确的说,只有某些时候,这种跨站访问资源,才被称为盗链。假设B站点作为一个商业网站,有很多自主版权的图片,自身展示用于商业目的。而A站点,希望在自己的网站上面也展示这些图片,直接使用:<img src="http://b.com/photo.jpg"/>
这样,大量的客户端在访问A站点时,实际上消耗了B站点的流量,而A站点却从中达成商业目的。从而不劳而获。这样的A站点着实令B站点不快的。那么如何禁止此类问题呢?
HTTP协议和标准的浏览器对于解决这个问题提供便利,浏览器在加载非本站的资源时,会增加一个头域,头域名字固定为:Referer
而在直接粘贴地址到浏览器地址栏访问时,请求的是本站的该url的页面,是不会有这个referer这个http头域的。使用Chrome浏览器的调试台,打开network标签可以看到每一个资源的加载过程,下面两个图分别是主页面和一个页面内资源的加载请求截图:
这个referer标签正是为了告诉请求响应者(被拉取资源的服务端),本次请求的引用页是谁,资源提供端可以分析这个引用者是否“友好”,是否允许其“引用”,对于不允许访问的引用者,可以不提供图片,这样访问者在页面上就只能看到一个图片无法加载的浏览器默认占位的警告图片,甚至服务端可以返回一个默认的提醒勿盗链的提示图片。
一般的站点或者静态资源托管站点都提供防盗链的设置,也就是让服务端识别指定的Referer,在服务端接收到请求时,通过匹配referer头域与配置,对于指定放行,对于其他referer视为盗链。
点击了解Nginx配置防盗链
2.2 跨域访问原理
维基上面给出了跨站访问的危害性。从这里可以整理出跨站访问的定义:JS脚本在浏览器端发起的请求其他域(名)下的网站数据的HTTP请求。
这里要与referer区分开,referer是浏览器的行为,所有浏览器发出的请求都不会存在安全风险。而由网页加载的脚本发起请求则会不可控,甚至可以截获用户数据传输到其他站点。referer方式拉取其他网站的数据也是跨域,但是这个是由浏览器请求整个资源,资源请求到后,客户端的脚本并不能操纵这份数据,只能用来呈现。但是很多时候,我们都需要发起请求到其他站点动态获取数据,并将获取到底数据进行进一步的处理,这也就是跨域访问的需求。
2.2.1 JSONP跨域原理
利用浏览器的Referer方式加载脚本到客户端的方式。以:
<script type="text/javascript" src="http://api.com/jsexample.js"></script>
这种方式获取并加载其他站点的JS脚本是被允许的,加载过来的脚本中如果有定义的函数或者接口,可以在本地使用,这也是我们用得最多的脚本加载方式。但是这个加载到本地脚本是不能被修改和处理的,只能是引用。而跨域访问需要正是访问远端抓取到的数据。那么能否反过来,本地写好一个数据处理函数,让请求服务端帮助完成调用过程?JS脚本允许这样。
<script type="text/javascript">
var localHandler = function(data){alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
};
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
端的服务器上面定义的remote.js是这样的:
localHandler({"result":"我是远程js带来的数据"});
面首先在本地定义了一个函数localHandler,然后远端返回的JS的内容是调用这个函数,返回到浏览器端执行。同时在JS内容中将客户端需要的数据返回,这样数据就被传输到了浏览器端,浏览器端只需要修改处理方法即可。
这里有一些限制:
- 客户端脚本和服务端需要一些配合;
- 调用的数据必须是json格式的,否则客户端脚本无法处理;
- 只能给被引用的服务端网址发送get请求。
<script type="text/javascript">
var localHandler = function(data)
{alert('我是本地函数,可以被跨域的remote.js文件调用,远程js带来的数据是:' + data.result);
};
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.php?callBack=localHandler"></script>
务端的PHP函数可能是这样的:
<?php$data = ".......";
$callback = $_GET['callback'];
echo $callback.'('.json_encode($data).')';
exit;?>
这样即可根据客户端指定的回调拼装调用过程。
2.2.2 CORS跨域原理
上述的JSONP由于有诸多限制,已经无法满足各种灵活的跨域访问请求。现在浏览器支持一种新的跨域访问机制,基于服务端控制访问权限的方式。简而言之,浏览器不再一味禁止跨域访问,而是需要检查目的站点返回的消息的头域,要检查该响应是否允许当前站点访问。通过HTTP头域的方式来通知浏览器:
Response headers[edit]
Access-Control-Allow-Origin
Access-Control-Allow-Credentials
Access-Control-Expose-Headers
Access-Control-Max-Age
Access-Control-Allow-Methods
Access-Control-Allow-Headers
服务端利用这几个HTTP头域通知浏览器该资源的访问权限信息。在访问资源前,浏览器会先发出OPTIONS请求,获取这些权限信息,并比对当前站点的脚本是否有权限,然后再将实际的脚本的数据请求发出。发现权限不允许,则不会发出请求。逻辑流程图为:
浏览器也可以直接将GET请求发出,数据和权限同时到达浏览器端,但是数据是否交给脚本处理需要浏览器检查权限对比后作出决定。
一次具体的跨域访问的流程为:
因此权限控制交给了服务端,服务端一般也会提供对资源的CORS的配置。
跨域访问还有其他几种方式:本站服务端代理、跨子域时使用修改域标识等方法,但是应用场景的限制更多。目前绝大多数的跨域访问都由JSONP和CORS这两类方式组成。
2.3 同源策略
在浏览器中,内容是很开放的,任何资源都可以接入其中,如 JavaScript
文件、图片、音频、视频等资源,甚至可以下载其他站点的可执行文件。
但也不是说浏览器就是完全自由的,如果不加以控制,就会出现一些不可控的局面,例如会出现一些安全问题,如:
- 跨站脚本攻击(XSS)
- SQL 注入攻击
- OS 命令注入攻击
- HTTP 首部注入攻击
- 跨站点请求伪造(CSRF)
- 等等…
如果这些都没有限制的话,对于我们用户而言,是相对危险的,因此需要一些安全策略来保障我们的隐私和数据安全。
这就引出了最基础、最核心的安全策略:同源策略
。
2.3.1 什么是同源策略
同源策略
是一个重要的安全策略,它用于限制一个源的文档或者它加载的脚本如何能与另一个源的资源进行交互。
如果两个 URL
的协议、主机和端口都相同,我们就称这两个 URL
同源。
协议
:协议
是定义了数据如何在计算机内和之间进行交换的规则的系统,例如 HTTP、HTTPS。主机
:是已连接到一个计算机网络的一台电子计算机或其他设备。网络主机可以向网络上的用户或其他节点提供信息资源、服务和应用。使用TCP/IP
协议族参与网络的计算机也可称为 IP 主机。端口
:主机是计算机到计算机之间的通信,那么端口就是进程到进程之间的通信。
如下表给出了与 URL http://test.home.com:8080/dir/page.html 的源进行对比的示例:
URL | 结果 | 原因 |
---|---|---|
http://test.home.com:8080/dir/page123.html | 同源 | 只有路径不同 |
http://test.home.com:8080/dir/inner/another.html | 同源 | 只有路径不同 |
https://test.home.com:8080/dir/page.html | 不同源 | 只有路径不同 |
http://test.home.com:8081/dir/page.html | 不同源 | 只有路径不同 |
http://online.home.com:8080/dir/page.html | 不同源 | 只有路径不同 |
同源策略主要表现在以下三个方面:DOM
、Web 数据
和网络
DOM 访问限制
:同源策略限制了网页脚本(如JavaScript
)访问其他源的DOM
。这意味着通过脚本无法直接访问跨源页面的DOM
元素、属性或方法。这是为了防止恶意网站从其他网站窃取敏感信息。Web 数据限制
:同源策略也限制了从其他源加载的Web
数据(例如XMLHttpRequest 或 Fetch API
)。在同源策略下,XMLHttpRequest 或 Fetch
请求只能发送到与当前网页具有相同源的目标。这有助于防止跨站点请求伪造(CSRF)等攻击。网络通信限制
:同源策略还限制了跨源的网络通信。浏览器会阻止从一个源发出的请求获取来自其他源的响应。这样做是为了确保只有受信任的源能够与服务器进行通信,以避免恶意行为。
出于安全原因,浏览器限制从脚本内发起的跨源 HTTP
请求,XMLHttpRequest 和 Fetch API
,只能从加载应用程序的同一个域请求 HTTP
资源,除非使用 CORS
头文件
2.3.2 CORS
对于浏览器限制这个词,要着重解释一下:不一定是浏览器限制了发起跨站请求,也可能是跨站请求可以正常发起,但是返回结果被浏览器拦截了。
浏览器将不同域的内容隔离在不同的进程中,网络进程负责下载资源并将其送到渲染进程中,但由于跨域限制,某些资源可能被阻止加载到渲染进程。如果浏览器发现一个跨域响应包含了敏感数据,它可能会阻止脚本访问这些数据,即使网络进程已经获得了这些数据。CORB
的目标是在渲染之前尽早阻止恶意代码获取跨域数据。
CORB
是一种安全机制,用于防止跨域请求恶意访问跨域响应的数据。渲染进程会在CORB
机制的约束下,选择性地将哪些资源送入渲染进程供页面使用。
例如,一个网页可能通过 AJAX
请求从另一个域的服务器获取数据。虽然某些情况下这样的请求可能会成功,但如果浏览器检测到请求返回的数据可能包含恶意代码或与同源策略冲突,浏览器可能会阻止网页访问返回的数据,以确保用户的安全。
跨源资源共享(Cross-Origin Resource Sharing,CORS
)是一种机制,允许在受控的条件下,不同源的网页能够请求和共享资源。由于浏览器的同源策略限制了跨域请求,CORS
提供了一种方式来解决在 Web
应用中进行跨域数据交换的问题。
CORS
的基本思想是,服务器在响应中提供一个标头(HTTP 头
),指示哪些源被允许访问资源。浏览器在发起跨域请求时会先发送一个预检请求(OPTIONS
请求)到服务器,服务器通过设置适当的 CORS
标头来指定是否允许跨域请求,并指定允许的请求源、方法、标头等信息。
2.3.3 简单请求
不会触发 CORS
预检请求。这样的请求为 简单请求,若请求满足所有下述条件,则该请求可视为 简单请求:
HTTP
方法限制:只能使用GET、HEAD、POST
这三种HTTP
方法之一。如果请求使用了其他HTTP
方法,就不再被视为简单请求。- 自定义标头限制:请求的
HTTP
标头只能是以下几种常见的标头:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type(仅限于 application/x-www-form-urlencoded、multipart/form-data、text/plain)
。HTML
头部header field
字段:DPR、Download、Save-Data、Viewport-Width、WIdth
。如果请求使用了其他标头,同样不再被视为简单请求。 - 请求中没有使用
ReadableStream
对象 - 不使用自定义请求标头:请求不能包含用户自定义的标头。
- 请求中的任意
XMLHttpRequestUpload
对象均没有注册任何事件监听器;XMLHttpRequestUpload
对象可以使用XMLHttpRequest.upload
属性访问
2.3.4 预检请求
非简单请求的 CORS
请求,会在正式通信之前,增加一次 HTTP
查询请求,称为 预检请求
需预检的请求要求必须首先使用 OPTIONS
方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。预检请求
的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
例如删除一条记录
它首先会发起一个预检请求,预检请求的头信息包括两个特殊字段:
Access-Control-Request-Method
:该字段是必须的,用来列出浏览器的CORS
请求会用到哪些HTTP
方法,上例是POST
。Access-Control-Request-Headers
:该字段是一个逗号分隔的字符串,指定浏览器CORS
请求会额外发送的头信息字段,上例是content-type,x-secsdk-csrf-token
。access-control-allow-origin
:在上述例子中,表示https://xxx.cn
可以请求数据,也可以设置为*
符号,表示统一任意跨源请求。access-control-max-age
:该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是 1 天(86400 秒),即允许缓存该条回应 1 天(86400 秒),在此期间,不用发出另一条预检请求。
一旦服务器通过了 预检请求,以后每次浏览器正常的 CORS
请求,就都跟简单请求一样,会有一个 Origin
头信息字段。服务器的回应,也都会有一个 Access-Control-Allow-Origin
头信息字段。
2.3.5 附带身份凭证的请求与通配符
在响应附带身份凭证的请求时:
- 为了避免恶意网站滥用
Access-Control-Allow-Origin
头部字段来获取用户敏感信息,服务器在设置时不能将其值设为通配符*
。相反,应该将其设置为特定的域,例如:Access-Control-Allow-Origin: https://xxx.cn
。通过将Access-Control-Allow-Origin
设置为特定的域,服务器只允许来自指定域的请求进行跨域访问。这样可以限制跨域请求的范围,避免不可信的域获取到用户敏感信息。 - 为了避免潜在的安全风险,服务器不能将
Access-Control-Allow-Headers
的值设为通配符*
。这是因为不受限制的请求头可能被滥用。相反,应该将其设置为一个包含标头名称的列表,例如:Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
。通过将Access-Control-Allow-Headers
设置为明确的标头名称列表,服务器可以限制哪些自定义请求头是允许的。只有在允许的标头列表中的头部字段才能在跨域请求中被接受。 - 为了避免潜在的安全风险,服务器不能将
Access-Control-Allow-Methods
的值设为通配符*
。这样做将允许来自任意域的请求使用任意的HTTP
方法,可能导致滥用行为的发生。相反,应该将其设置为一个特定的请求方法名称列表,例如:Access-Control-Allow-Methods: POST, GET
。通过将Access-Control-Allow-Methods
设置为明确的请求方法列表,服务器可以限制哪些方法是允许的。只有在允许的方法列表中的方法才能在跨域请求中被接受和处理。 - 对于附带身份凭证的请求(通常是 Cookie)
这是因为请求的标头中携带了Cookie
信息,如果Access-Control-Allow-Origin
的值为*
,请求将会失败。而将Access-Control-Allow-Origin
的值设置为https://xxx.cn
,则请求将成功执行。
另外,响应标头中也携带了 Set-Cookie 字段,尝试对 Cookie 进行修改。如果操作失败,将会抛出异常。
2.3.6 完整的请求流程图
2.3.7 总结
预检请求是在进行跨域资源共享 CORS
时,由浏览器自动发起的一种 OPTIONS
请求。它的存在是为了保障安全,并允许服务器决定是否允许跨域请求。
跨域请求是指在浏览器中向不同域名、不同端口或不同协议的资源发送请求。出于安全原因,浏览器默认禁止跨域请求,只允许同源策略。而当网页需要进行跨域请求时,浏览器会自动发送一个预检请求,以确定是否服务器允许实际的跨域请求。
预检请求中包含了一些额外的头部信息,如 Origin
和 Access-Control-Request-Method
等,用于告知服务器实际请求的方法和来源。服务器收到预检请求后,可以根据这些头部信息,进行验证和授权判断。如果服务器认可该跨域请求,将返回一个包含 Access-Control-Allow-Origin
等头部信息的响应,浏览器才会继续发送实际的跨域请求。
使用预检请求机制可以有效地防范跨域请求带来的安全风险,保护用户数据和隐私。
3 四种跨域方法
3.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 的流程。
3.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 协议,端口都是 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.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 类型的数据。
3.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 对象。
这篇关于计算机基础之域名,跨域,防盗链的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!