34

对于跨域,每一个前端同学都不陌生,关于如何解决跨域也有很多种方法,这里我就总结一下什么是跨域、为什么会跨域以及我常用的解决跨域请求的几种方式。

跨域

浏览器同源策略: 浏览器限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
同源策略的具体表现:
  1)http请求不能向不同源的服务器发起HTTP请求
  2)非同源的网页不能共享Cookie、LocalStorage、IndexDB
  3)禁止对不同源页面的DOM进行操作。主要场景是iframe跨域的情况,不同域名的iframe限制相互访问
同源: 请求URL地址中的协议、域名及端口号都相同,只要有一个不相同就是跨域。
  例子:
    域名: http://www.example.com
    跨域请求:
      https://www.example.com //协议不同
      http://api.example.com //域名不同
      http://www.example.com:8080 //端口号不同

解决跨域请求的常用几种方案

解决方案:
  1)jsonp
  2)nginx反向代理
  3)配置vue-cli生成的文件实现代理
  4)后端设置CORS来解决跨域
注: 二、三两种都是服务器代理,因为跨域是浏览器的跨域限制,但是服务器不存在跨域问题,所以可以由服务器请求所要访问的资源然后再返回给客户端

JSONP

jsonp实现原理: <script>标签不受浏览器同源策略的影响,允许跨域引用资源。因此可以通过动态创建script标签,然后利用src属性进行跨域。
JSONP实现方式: 动态创建script标签,通过回调函数处理请求结果
JSONP的优点:
  1)可以跨域
  2)兼容性好
JSONP的缺点:
  1)只能支持GET请求,JSONP在调用失败时不会返回各种HTTP状态码
  2)安全性。如果提供JSONP的服务被人控制,那么所有调用这个JSONP的网站都存在漏洞。
下面是通过JSONP调用百度搜索的例子:

//HTML
<div class="wrap">
        <input type="text">
        <ul></ul>
</div>
//JS
let inpEle = document.querySelector('input');
    let ulEle = document.querySelector('ul');
    let interval = 0;

    function searchData(data) {
        if (data.g) {
            let result = data.g;
            let fragment = document.createDocumentFragment();
            let html = '';
            result.forEach( (item) => {
                html += `<li><a target="_blank" href="https://www.baidu.com/s?wd=${item.q}">${item.q}</a></li>`;
            } )
            ulEle.innerHTML = html;
        } else {
            ulEle.innerHTML = '';
        }
    }

    let scriptEle = null;
    inpEle.oninput = search;
    function search() {
        let val = inpEle.value;
        let now = new Date().getTime();

        if (now - interval > 300) {
            if (scriptEle) {
                scriptEle.remove();
            }
            scriptEle = document.createElement('script');
            // wd后面接的是关键字,cb后面接的回调函数的名称
            let url = 'https://www.baidu.com/sugrec?ie=utf-8&json=1&from=pc_web&prod=pc&wd='+ val + '&req=2&cb=searchData'
            scriptEle.src = url;
            document.body.appendChild(scriptEle);
        } 
    }

nginx反向代理

具体配置:
  1)安装nginx: http://nginx.org/en/download.... ,在其中选择要安装的版本,安装完成后解压
  2)配置要被代理的服务:
    在nginx-1.16.1 ==> conf ==> nginx.conf里进行配置(代码中找到server在里面添加代理即可):

   server{
       listen               80; //监听的端口
       server_name          localhost; // 在浏览器访问的host-name,根据这个来判断要代理到什么地方
        //    要代理的内容

// 第一步(可以不用)  进行反向代理,用localhost:80来代理http://127.0.0.1:8081的请求,可以根据自己起的本地服务器来进行修改
            location / {
                proxy_pass  http://127.0.0.1:8081;
            }

            // 第二步  接口代理,在/api的前面添加添加上指定的域名
            location /api {
                proxy_pass http://1.1.1.1:8080;  // 将/api的接口反向代理到这个服务器上,从而实现了跨域
            }
   }

  注:第一步是需要本地用编辑器起一个服务器,然后nginx做反向代理,从而实现在80端口下,访问非80端口的页面,这个配置完成后,浏览器的访问地址应该改为 localhost/index.html ;若是不想这么麻烦,可以在先将nginx-1.16.1 ==> html下的页面删掉,然后将代码移动到该位置即可,访问的地址为 http://localhost/index.html
  3)启动nginx.exe

vue代理配置

vue代理配置:
  图片描述

CORS

这个主要是后端做的,我就不说了,具体百度就可以。

以上就是我常用的几种跨域解决方案,如果大家有什么好的方法,欢迎赐教。

参考资料:
  浏览器同源策略及跨域的解决方法: https://www.cnblogs.com/laixi...
  MDN上的同源策略: https://developer.mozilla.org...
  MDN上的CORS: https://developer.mozilla.org...


雨夜望月
207 声望13 粉丝