常见解决跨域问题

154 阅读1分钟

什么是跨域

URL由协议、域名、端⼝和路径组成

何谓同源 : 如果两个URL的协议、域名和端⼝号相同,则表示他们同源。有⼀个不同就是跨域。

a891d5bfa04be0cdbf56eab929c469d.png

同源策略 :同源策略限制了从同⼀个源加载的⽂档或脚本如何与来⾃另⼀个源的资源进⾏交互。这是⼀个⽤于隔离潜在恶意⽂件的 重要安全机制。
同源策略限制以下几种行为:
1.  Cookie、LocalStorage 和 IndexDB 无法读取;
1.  DOM 和 Js对象无法获得;
1.  AJAX 请求不能发送;

跨域请求解决方案

  • Jsonp
  • 跨域资源共享 Cors
  • iframe
  • 服务器代理

Jsonp解决跨域问题

jsonp的原理就是利用script标签没有跨域限制,通过script标签src的属性,发送带有callback参数的GET请求,服务端将接口返回数据拼凑到callback函数中,返回给浏览器,浏览器解析执行,从而前端拿到callback函数返回的数据。

image.png

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

服务端返回如下(返回时即执行全局函数):

handleCallback({"success": true, "user": "admin"})

局限: Jsonp只支持处理GET请求。


Cors 跨域资源共享

  1. 客户端(发送ajax/fetch请求)可以允许携带cookie
  2. 服务器端设置相关的请求头信息(需要处理options试探性请求)Access-Control-Allow-Origin

http proxy =====>webpack webpack-dev-server

  1. 使用webpack-dev-server的http proxy代理

iframe + postMessage

Y1页面:

<body>
    <iframe id = 'iframe' src='http://xxxx/Y2.html' frameborder="0" style="dispaly=none;"><iframe>
<script>
    iframe.onload=function(){
        iframe.contentWindow.postMessage('yulele','http://xxxx/')
    }
    
    window.onmessage = function(e){
        console.log(e.data);
    }
 </script>
 </body>

Y2页面:

<body>
<script>
    window.onmessage = function(e){
        e.source.postMessage(e.data+'一些参数',e.origin);
    }
 </script>
 </body>
 

iframe + document.domain

只能实现:痛统一主域,不同子域之间的操作

父页面Y1

<iframe id = 'iframe' src='http://xxxx.com/Y2.html' frameborder="0" style="dispaly=none;">
<script>
  document.domain = 'xxxx.com';
  var user = 'admin';
</script>  

子页面Y2

<script>
     document.domain = 'xxxx.com';
     console.log(window.parent.user);
</script> 

iframe + window.name

Y1页面:

<iframe id = 'iframe' src='http://xxxx.com/Y2.html' frameborder="0" style="dispaly=none;">
<script>
    let count = 0;
    iframe.onload = function(){
        if(count===0){
            iframe.src = 'http://xxxx.com/proxy.html';   //proxy与Y1页面同源
            count++;
            return ;
        }
        console.log(iframe.contentWindow.name);
    }
</script>

Y2页面:

<script>
    //服务器需要返回给Y1的信息都存储在window.name里
    window.name = '123';
</script>