解决跨域问题的六种方式

151 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情

解决跨域问题的六种方式

同源策略

非同源时 1.) Cookie、LocalStorage 和 IndexDB 无法读取 2.) DOM 和 Js 对象无法获得 3.) AJAX 请求不能发送

JSONP

通过 jsonp 跨域

通常为了减轻 web 服务器的负载,我们把 js、css,img 等静态资源分离到另一台独立域名的服务器上,在 html 页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建 script,再请求一个带参网址实现跨域通信。 1.)原生实现:

 <script>
 var script = document.createElement('script');
 script.type = 'text/javascript'; // 传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
 script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
 document.head.appendChild(script); // 回调执行函数
 function handleCallback(res) {
     alert(JSON.stringify(res));
 }
</script>

服务端返回如下(返回时即执行全局函数): handleCallback({"status": true, "user": "admin"}) jsonp 缺点:只能实现 get 一种请求。

jqAjax

使用 jquery ajax 实现跨域,dataType 请求方式为 jsonp

$.ajax({
 url:'http://www.domain2.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp jsonpCallback: "handleCallback", // 自定义回调函数名 data: {} });

iframe

document.domain + iframe 跨域 此方案仅限主域相同,子域不同的跨域应用场景。 实现原理:两个页面都通过 js 强制设置 document.domain 为基础主域,就实现了同域。 1.)父窗口:(www.domain.com/a.html)

<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
  document.domain = 'domain.com';
  var user = 'admin';
</script>

2.)子窗口:(child.domain.com/b.html)

<script>
document.domain = 'domain.com'; // 获取父窗口中变量
alert('get js data from parent ---> ' + window.parent.user);
</script>

postMessage

postMessage 跨域

postMessage 是 HTML5 XMLHttpRequest Level 2 中的 API,且是为数不多可以跨域操作的 window 属性之一,它可用于解决以下方面的问题: a.) 页面和其打开的新窗口的数据传递 b.) 多窗口之间消息传递 c.) 页面与嵌套的 iframe 消息传递 d.) 上面三个场景的跨域数据传递 用法:postMessage(data,origin)方法接受两个参数 data: html5 规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用 JSON.stringify()序列化。 origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

1.)a.html:(www.domain1.com/a.html)

<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>
 var iframe = document.getElementById('iframe');
 iframe.onload = function() {
    var data = { name: 'aym' }; // 向domain2传送跨域数据
    iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
  }; // 接受domain2返回数据
  window.addEventListener('message', function(e) {
     alert('data from domain2 ---> ' + e.data);
   }, false);
</script>

2.)b.html:(www.domain2.com/b.html)

<script>
 // 接收domain1的数据
 window.addEventListener('message', function(e) {
    alert('data from domain1 ---> ' + e.data);
    var data = JSON.parse(e.data);
    if (data) {
        data.number = 16; // 处理后再发回domain1
        window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com');
     }
 }, false);
 </script>

跨域资源共享(CORS)

普通跨域请求:只服务端设置 Access-Control-Allow-Origin 即可,前端无须设置,若要带 cookie 请求:前后端都需要设置。 需注意的是:由于同源策略的限制,所读取的 cookie 为跨域请求接口所在域的 cookie,而非当前页。如果想实现当前页 cookie 的写入, 目前,所有浏览器都支持该功能(IE8+:IE8/9 需要使用 XDomainRequest 对象来支持 CORS)),CORS 也已经成为主流的跨域解决方案。

nginx

通过 nginx 代理,将两个不同域名下的页面处于同一父级域名

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情