前端跨域及常见的解决办法

54 views次阅读
没有评论

什么是跨域?

因为浏览器出于安全考虑,有同源策略。也就是说,如果协议、域名或者端口有一个不同就会产生跨域,此时Ajax 请求会失败。

同源策略会限制以下几种行为:
1. cookie、localStorage和indexDB无法读取
2. DOM和JS对象无法获取
3. Ajax请求无法发送

常见的解决办法

1. JSONP

JSONP 的原理很简单,就是利用 <script> 标签没有跨域限制的漏洞。当需要通讯时,通过 <script> 标签指向一个需要访问的地址并提供一个回调函数来接收数据。

  <script src="http://domain/api?param1=a&param2=b&callback=jsonp"></script>;
  <script>
    function jsonp(data) {
      console.log(data)
    }
  </script>

JSONP 使用简单且兼容性不错,但是只限于 get 请求。

在开发中可能会遇到多个 JSONP 请求的回调函数名是相同的,这时候就需要自己封装一个 JSONP,以下是简单实现:

  function jsonp(url, jsonpCallback, success) {
    let script = document.createElement("script");
    script.src = url;
    script.async = true;
    script.type = "text/javascript";
    window[jsonpCallback] = function(data) {
      success &amp;&amp; success(data);
    };
    document.body.appendChild(script);
  }
  jsonp(
    "http://xxx",
    "callback",
    function(value) {
      console.log(value);
    }
  );

2. CORS

CORS需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。

浏览器会自动进行 CORS 通信,实现CORS通信的关键是后端。只要后端实现了 CORS,就实现了跨域

服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。

3. document.domain

该方式只能用于二级域名相同的情况下,比如 a.test.comb.test.com 适用于该方式。

只需要给页面添加 document.domain = 'test.com' 表示二级域名都相同就可以实现跨域。

4. postMessage

这种方式通常用于获取嵌入页面中的第三方页面数据。一个页面发送消息,另一个页面判断来源并接收消息

  // 发送消息
  window.parent.postMessage('message', 'http://test.com');
  // 接收消息
  const mc = new MessageChannel();
  mc.addEventListener('message', (event) =&gt; {
    const origin = event.origin || event.originalEvent.origin;
    if (origin === 'http://test.com') {
      console.log('验证通过');
    }
  });

5. nginx代理跨域

实质和CORS跨域原理一样,通过配置文件设置请求响应 Access-Control-Allow-origin 等字段。

(1). nginx配置解决iconfont跨域
浏览器访问js、css、img等常规静态资源是被同源策略许可的,但iconfont字体文件不会,此时可以修改配置文件如下:

  location / {
    add_header Access-Control-Allow-origin *;
  }

(2). nginx反向代理接口跨域
原理: 通过nginx配置一个代理服务器域名与domain相同(端口不同)来做跳板,反向代理访问domain2接口,并且可以修改cookie中domain的信息,方便当前域cookie写入,实现跨域访问。 配置如下:

  #proxy服务器
  server {
    listen   81;
    server_name  www.domain1.com;

    location / {
      proxy_pass   http://www.domain2.com:8080;  #反向代理
      proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名
      index  index.html index.htm;

      # 当用webpack-dev-server等中间件代理接口访问nignx时,此时无浏览器参与,故没有同源限制,下面的跨域配置可不启用
      add_header Access-Control-Allow-Origin http://www.domain1.com;  #当前端只跨域不带cookie时,可为*
      add_header Access-Control-Allow-Credentials true;
    }
  }

6. vue.config.js

如果是vue-cli创建的vue项目,可以在vue.config.js中配置代理跨域。

  devServer: {
    host: 'localhost',
    port: 8080, // 端口号
    hotOnly: false,
    https: false, // https:{type:Boolean}
    open: false, // 配置自动启动浏览器
    proxy: {
      '/api': {
        target: 'http://192.168.1.197:9102/', // 这里后台的地址模拟的,使用时应该填写真实的后台接口地址
        ws: true,
        changOrigin: true, // 允许跨域
        pathRewrite: {
          '^/api': '' // 请求的时候使用这个api就可以
        }
      }
    } // 配置跨域处理,只有一个代理
  }

1
guxuerui
版权声明:本站原创文章,由guxuerui于2020年07月31日发表,共计3730字。
转载提示:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)
Loading...