跨域的理解和解决办法

一、跨域是什么?
跨域,指的是浏览器不能执行其他网站的脚本
当前页面的url 与 请求url的协议域名端口三个其中任意一个不同时都会产生跨域。

当前url 请求的url 是否跨域 跨域原因
https://www.baidu.com https://www.baidu.com/a.js 同源
https://www.baidu.com http://www.baidu.com/a.js 协议不同,一个是https,一个是http
https://www.baidu.com https://www.baidu.com:8080/a.js 端口号不同
https://www.baidu.com https://www.test.com/a.js 域名不同

二、为什么会有跨域
由于浏览器的同源策略限制。同源策略是一种约定,它是浏览器最核心和最基本的安全功能。web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的js脚本和另一个域的脚本进行交互。跨域限制访问,其实是浏览器的限制。

三、不同源的限制

  1. 无法读取不同源网页的cookie、localstorage、indexedDB
  2. 无法接触不同源网页的DOM
  3. 无法像不同源地址发送请求

四、前端开发常见跨域场景
前端开发过程中,在开发模式时,项目启动地址 和 部署在服务器上的数据接口地址 不同源,就会产生跨域,就会请求不到数据。

五、怎么解决跨域问题?

  1. DOM层面和数据层面
    1.1 设置document.domain解决无法读取非同源网页的 Cookie问题
    document.domain是存放文档的服务器的主机名, 因为浏览器是通过document.domain属性来检查两个页面是否同源,因此只要 通过设置相同的document.domain,两个页面就可以共享Cookie(此方案仅限主域相同,子域不同的跨域应用场景。)

    // 两个页面都设置
    document.domain = 'test.com';
    

    1.2 跨文档通信 API:window.postMessage()
    window.postMessage是HTML5新增的跨文档通信API,该API,允许跨窗口通信,不论这两个窗口是否同源。

    适合以下需求:
    
     - 页面和其打开的新窗口间数据传递
     - 多窗口间消息传递
     - 页面与嵌套的iframe消息传递
     - 上面三个场景的跨域数据传递
    
    //父页面向打开的新窗口发送消息
    var openWindow = window.open('http://test.com', 'massage');
    openWindow.postMessage('Nice to meet you!', 'http://test.com');
    
    // 新窗口监听 message 消息
    window.addEventListener('message', function (e) {
          
          
      console.log(e.source); // e.source 发送消息的窗口
      console.log(e.origin); // e.origin 消息发向的网址
      console.log(e.data);   // e.data   发送的消息
    },false);
    
    

    1.3 window.name
    浏览器窗口有window.name属性,这个属性的最大特点是,无论是否同源,只要在同一个窗口里,前一个网页设置了这个属 性,后一个网页可以读取它。如果需要实现父页面和跨域的子页面之间的通信,需要一个和父页面同源的子页面作为中介,将跨域的子页面中的信息传递过来。

    1.4 片段标识符
    通过监听url中hash的改变来实现数据的传递

    //父页面
    <div>
    	<iframe src="./childHtml.html" id="childHtmlId"></iframe>
    </div>
    
    let ifraneDom = document.getElementById('childHtmlId')
    iframeDom.src += '#父传递给子'
    
    //子页面
    window.onhashchange = function() {
          
          
       console.log(decodeURIComponent(window.location.hash));
    };
    
    
  2. 网络层面
    根据同源策略,浏览器默认是不允许XMLHttpRequest对象访问非同一站点的资源的,所以需要破解这种限制,实现跨域访问资源。目前主要采用以下几种方式。
    1.代理
    将请求代理到同源的服务器上,可以使用Nginx、Node中间件等
    2.JSONP
    JSONP借助script元素实现跨域技术,得益于script元素有这两种特点:src不受同源策略影响,能访问任何url资源;如果访问的资源包括js代码,会在下载后自动执行。
    JSONP只支持get请求,网页通过添加一个< script >标签元素,像服务器请求JSON数据,服务器接收到请求后,将数据放在指定名字的回调函数参数位置传回来

    原生
    <script src="http://website.com/getData?callback=getData"></script>
    回调函数
    <script type="text/javascript">
    	function getData(data){
          
          
         //拿到数据
        }
    </script>
    
    vueJs
    this.$http.jsonp('ttp://website.com/getData?callback=getData', {
          
          
    	params: {
          
          },
    	jsonp: 'handleCallback'
    }).then(res => {
          
          
    	//res
    )
    

    3.CORS 方式
    CORS (Cross-Origin Resource Sharing)

    1、普通跨域请求:只需服务器端设置Access-Control-Allow-Origin
    2、带cookie跨域请求:前后端都需要进行设置
    
    前端设置: 根据xhr.withCredentials字段判断是否带有cookie
    服务端设置: 服务器端对于CORS的支持,主要是通过设置Access-Control-Allow-Origin来进行的。如果浏览器检测到相应的设置,就可以允许Ajax进行跨域的访问。
    

参考文章
https://blog.csdn.net/qq_38128179/article/details/84956552
https://juejin.cn/post/6981008064543457294

猜你喜欢

转载自blog.csdn.net/Tiny2017/article/details/118492538