实战跨域
还是有一些漏网之鱼的
HTMLlink标签和CSSurl函数
link引入一个外部样式表。url指向一个资源,许多css属性都可以使用它,例如
@font-face
list-style
cursor等。
这是一个Material Design风格的按钮,这里通过link
引入material-components-web样式,@font-face引入Material
Icons字体文件。
@font-face {
font-family: 'Material Icons';
font-style: normal;
font-weight: 400;
src: url(//fonts.gstatic.com/s/materialicons/v70/flUhRq6tzZclQEJ-Vdg-IuiaDsNc.woff2) format('woff2');
}
.material-icons {
font-family: 'Material Icons';
font-weight: normal;
font-style: normal;
font-size: 24px;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-webkit-font-smoothing: antialiased;
}
HTMLscript标签
script
可以嵌入和引入外部可执行脚本,这里主要说的是引入跨域的JS。下面还是material-components-web的一个示例,只不过依赖JS:
var slider = new mdc.slider.MDCSlider(document.querySelector('.mdc-slider'));
HTMLimg标签
img标签可以嵌入图像。 这里使用了百度的图片。
HTMLvideo
audio标签
HTMLiframe标签
这种方式也是可以禁止的,MDN Web 文档就不可以。这里使用
iframe嵌入多吉搜索
cookie(有限制)
cookie
未遵循严格的同源策略,但是也是有限制的。//ddz.com/index.html 页面设置cookie时如果不指定domain
,iframe中 c1.ddz.com/cookie1.html 该页面不获取父页面的cookie。
● 主域名是不给子域名设置cookie的。例如://ddz.com/index.html => document.cookie =
"name=index.html;domain=c1.ddz.com";
● 主域名不设置domain,子域名是不能访问的。例如://ddz.com/index.html => document.cookie =
"name=index.html;";之后 //c1.ddz.com/cookie1.html => document.cookie,这里不能获取主域名设置的cookie
● 主域名设置domain,子域名可以能访问。例如://ddz.com/index.html => document.cookie =
"name=index.html;domain=ddz.com";之后 //c1.ddz.com/cookie1.html => document.cookie
这就就可以获取到了。如果你在浏览器F12中查看,你会发现主域名设置cookie会同时添加到子域名下
● 子域名设置domain,主域名可以能访问。例如://c1.ddz.com/cookie1.html => document.cookie =
"age=18;domain=ddz.com";之后 //ddz.com/index.html => document.cookie 就可以取到
你不能做的一些事情
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
上面的问题可以解决吗?
先介绍一下测试环境。服务器用的是IIS,搭了一个站点,路径为"/p/web/problem/crossDomain";之后修改hosts文件,如下:
127.0.0.1 ddz.com
127.0.0.1 c1.ddz.com
127.0.0.1 c2.ddz.com
iframe搭配
document.domain
先说一下,主域名下的页面不能设置document.domain为子域名,否则会报错。例如: //ddz.com/index.html =>
document.domain = 'c1.ddz.com';
Uncaught DOMException: Failed to set the 'domain' property on 'Document': 'c1.ddz.com' is not a suffix
of 'ddz.com'.
还有一点就是相应页面设置document.domain的时机,一定保证在跨域读取之前已经设置完成,否则还是会报跨域错误。
Uncaught DOMException: Blocked a frame with origin "http://c1.ddz.com" from accessing a cross-origin
frame.
最后一点就是你可以在 //ddz.com/index.html 页面打印输出document.domain
,值为:"ddz.com"。但是如果你不显示设置他的值,照样是跨域错误。
documentDomain1.html:11 Uncaught DOMException: Blocked a frame with origin "http://c1.ddz.com" from
accessing a cross-origin frame.
index.html:232 Uncaught DOMException: Blocked a frame with origin "http://ddz.com" from accessing a
cross-origin frame.
iframe搭配
location.hash
在 //ddz.com/index.html 页面通过使用iframe并且设置路径时带上hash
值的方式给跨域页面传值,这并没有什么问题。问题是iframe
中的页面应答,该页面也可以通过上面的方式将相应传给与父页面同源的页面,例如:'//ddz.com/locationHash0.html#' + new Date().valueOf(); ,在
//ddz.com/locationHash0.html 这个页面就是通过window.parent.parent.location.hash设置
//ddz.com/index.html 页面的hash了。这可真够费劲的,子页面不能像parent.location.href =
parent.location.href + "#" + new Date().valueOf();或者parent.location.hash =
new Date().valueOf();这样
修改父页面的hash吗?答案是不可以的,虽然是主域和子域的关系,会报下面的错误。
locationHash1.html:17 Uncaught DOMException: Blocked a frame with origin "http://c1.ddz.com" from
accessing a cross-origin frame.
此处的测试想要成功需要将上文中的document.domain = 'ddz.com';这句代码屏蔽掉。
iframe搭配
window.name
在 //ddz.com/index.html 页面通过使用iframe嵌入 //c1.ddz.com/windowName1.html 页面(该页面设置
window.name),onload之后再利用该iframe去加载和 //ddz.com/index.html
页面同源的页面://ddz.com/windowName0.html。这时读取iframe
contentWindow.name
的值,这里获取到的就是第一次加载跨域页面设置的window.name。注意:第二次加载的同源页面不要设置
window.name,否则获取到的就是他的值了。
此处的测试想要成功需要将上文中的document.domain = 'ddz.com';这句代码屏蔽掉。
安全的跨源通信postMessage
JSONP
这里调用JSONP 教程 | 菜鸟教程获取数据
代理服务器、WebSocket、CORS等
这几种方式都和服务器端相关并且不太好测试,这里暂时就不写了……以后再说
参考链接