
因为浏览器的同源策略而产生跨域问题,跨域主要是为了用户的上网安全。下面例举了前端最常见的三个跨域,以及处理方式
iframe跨域主要是为了防止恶意网站获取其他网站的dom,拿去私密信息,如果没有跨域恶意网站可以嵌套其他网站,比如https://mail.qq.com/,当用户输入用户名密码时通过dom即可截取到。当然也有一些业务确实确实需要跟子页面通讯,下面列举了一系列iframe跨域的处理方式
document.domain的作用就是获取/设置当前文档的原始域名,默认值就是当前域名。可设置的值为父域名|当前域名。比如a.demo.com可设置的值就是a.demo.com|demo.com。浏览器判断跨域时会使用document.domain来判断是否域名跨域。
所以我们子域名与子域名使用iframe跨域时,双方的document.domain都设置为父域名。父域名与子域名使用iframe跨域时,子域名将document.domain设置为父级域名。
window.name可读可写,值是跟着浏览器窗体走的,也就是说不是跟着页面走的,我们在使用iframe加载子页面时,子页面可以通过name来传递值给父级使用。
// 子页面
window.name = JSON.stringify({ title: "child" });
// 父页面
const $iframe = document.createElement("iframe");
$iframe.src = "";
$iframe.onload = () => {
// '{"title":"child"}'
console.log($iframe.contentWindow.name);
};
document.body.appendChild($iframe);
window.postMessage方法可以安全的实现跨通讯,使用时在发送方明确接收方的协议、地址、端口号就可以发送,接收方使用message事件监听来自postMessage的事件。
// 子页面 b
parent.postMessage("toggleFullScreen", "http://a.demo.com");
// 父页面 a
window.addEventListener("message", (event) => {
if (event.origin === "http://b.demo.com") {
// event.data 发送的消息
window[event.data]();
// event.source 获取发送方的window
event.source.postMessage(`${event.data}Success`, event.origin);
}
});
AJAX跨域主要是放置恶意网站请求其他网站,因为请求中会携带cookie服务器会误认为是“本人”操作而引发安全问题。比如用户登录了银行网站,然后访问恶意网站,恶意网站请求转账到指定账户,此时请求会携带上用户信息到银行服务器。当然也有一些业务确实跨域请求其他服务器,下面列举了一系列AJAX跨域的处理方式
ajax请求收到同源策略影响,但是script标签的src属性不会,可以访问跨域的js脚本。我们可以利用这个特性,在服务端不返回JSON格式,而是返回某个函数执行代码。
const $script = document.createElement("script");
$script.src = `http://www.xxx.com/?callback=getData`;
const getData = (data) => {
console.log(data);
};
document.body.appendChild($script);
// 服务端返回e
// getData({ ... })
JSONP只支持get而且需要后端配合
请求时,服务端在 HTTP 响应头设置Access-Control-Allow-Origin允许当前域跨域,浏览器就会允许跨域行为
Access-Control-Allow-Origin: *
Access-Control-Allow-Origin: <origin>
上方的请求是不携带凭证 (如 cookie) ,也就是说服务器无法认证你的信息,比如我们再 A 网站登录了,在 B 网站通过AJAX请求 A 网站是无法拿到需要凭证的信息的 _(如用户信息)_, 如果需要带上cookie还需要做其他处理,参考我之前写过的文章
在客户端浏览器发起一个非同源请求会产生跨域问题,但是服务端并没有同源策略,服务端向另一个服务器发起请求不会产生跨域问题。那我们可以将请求统一到同源的服务器,对于要跨域的请求加上特定标识的 url 前缀,在服务器上匹配如果是这个前缀的请求,则反向代理到跨域服务器。
我们在代理中还可以修改Cookie的domain信息,方便当前域Cookie的写入。
这是目前最常用的方式,本地开发的跨域可以在本地建立代理,如果是线上则在线上创建代理。
canvas提供了一个通过JavaScript和HTML元素来绘制图形的方式,canvas可以从其他站点加载其他站点的资源,比如图片。在跨站引入资源没有处理时,canvas会被污染,只要被污染的画布就无法获取画布数据,如toBlob、toDataURL、getImageData一类api,这就产生的跨域问题。
canvas产生的跨域问题跟AJAX的处理方式差不多,可以借助Proxy,或者在 HTTP 响应头设置Access-Control-Allow-Origin。除此之外还需要对资源通过crossorigin属性声明不需要凭证信息。
| 属性值 | 描述 |
|---|---|
anonymous |
对此元素的CORS请求将不设置凭证标志 |
use-credentials |
对此元素的CORS请求将设置凭证;这意味着请求将携带凭证 |
"" |
设置空值,与设置anonymous效果一致 |
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const img = new Image()
img.crossOrigin = 'anonymous'
img.onload = function () {
context.drawImage(this, 0, 0)
context.getImageData(0, 0, this.width, this.height);
};
img.src = 'xxx'
如果需要携带凭证除了声明crossOrigin属性值为use-credentials外还需要做其他处理,参考我之前写过的文章。
完结撒花
©2021 - bill-lai 的小站 -站点源码