[TOC]

(一) 什么跨域

  1. 知其然知其所以然,在说跨域方法之前,我们先了解下什么叫跨域,浏览器有同源策略,只有当“协议”、“域名”、“端口号”都相同时,才能称之为是同源,其中有一个不同,即是跨域。
  2. 那么同源策略的作用是什么呢?同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
  3. 那么我们又为什么需要跨域呢?一是前端页面和服务器分开部署,接口请求需要跨域,二是我们可能会加载其它网站的页面作为 iframe 内嵌。 ```javascript <!DOCTYPE html>

<a name="P2QxR"></a>
## (二) 跨域有哪些方式

1. jsonp 跨域(优点:简单方便,缺点:只能使用 get 请求,不支持 post 请求)
1. 使用代理进行跨域
   1. nginx 的反向代理 
   1. axios 反向代理
   1. vue 跨域设置
3. cors(跨域资源共享)修改服务器端修改包的头部信息,
3. window.name(少用)
3. iframe 跨子域(不常用)
3. fetch
<a name="jrH1j"></a>
## (三) 常用见的跨域方式有哪些
<a name="jNXWl"></a>
#### 1. jsonp 跨域
jsonp跨域原理: 尽管浏览器有同源策略,但是 <script> 标签的 src 属性不会被同源策略所约束,可以获取任意服务器上的脚本并执行。jsonp 通过插入 script 标签的方式来实现跨域,参数只能通过 url 传入,仅能支持 get 请求。jsonp跨域前后实现代码
```javascript
// 后端代码,使用koa实现
const Koa = require("koa");
const app = new Koa();
app.use(ctx => {
  let callback = ctx.query.callback;
  let data = {
    code: 666,
    msg: 'success',
    data: {
      useranme: 'laohu',
      age: 100,
    }
  }
  let dataStr = JSON.stringify(data);

  let res = `${callback}(${dataStr})`;
  ctx.body = res;
});

app.listen(3000, () => {
  console.log("http://localhost:3000");
});
<!--前端代码-->
<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>

<body>

    <script>
        // 给body添加scipt标签
        var script = document.createElement('script');
        script.src = 'http://huruqing.cn:5024/userJsonp?callback=getData';
        document.body.appendChild(script);

        // 声明getData函数
        function getData(res) {
            console.log(res);
        }
    </script>
</body>

</html>

2.1 jQuery跨域

$.ajax({
  url: 'http://www.test.com:8888/getData',
  type: 'get',
  dataType: 'jsonp',  // 请求方式为jsonp 
  data: {},
  success: function(res){},
  error: function() {}
})

2.2 vue使用代理进行跨域

在vue中使用proxy进行跨域的原理是:将域名发送给本地的服务器(启动vue项目的服务,loclahost:8080),再由本地的服务器去请求真正的服务器。

devServer: {
  // 代理
  proxy: {
    // 只要请求地址有'api'都会匹配上
    "/api": {
      // 目标接口地址
      target: "http://232.132.99.11:3006",
      ws: true,
      // 允许跨域
      changeOrigin: true,
      pathRewrite: {
        "^/api": "" //通过pathRewrite重写地址,将前缀/api转为/
      }
    }
  }
}

2.3 nginx 反向代理

A 网站向 B 网站请求某个接口时,向 B 网站发送一个请求,nginx 根据配置文件接收这个请求,代替 A 网站向 B 网站来请求。 nginx 拿到这个资源后再返回给 A 网站,以此来解决了跨域问题。
例如 nginx 的端口号为 8090,需要请求的服务器端口号为 3000。
nginx 配置如下:

server {
    listen       8090;

    server_name  localhost;

    location / {
        root   /Users/liuyan35/Test/Study/CORS/1-jsonp;
        index  index.html index.htm;
    }
    location /say {
        rewrite  ^/say/(.*)$ /$1 break;
        proxy_pass   http://localhost:3000;
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
    }
  ## others
}

3. 服务器跨域(nodejs中间件)

app.use((ctx, next) => {
    ctx.set("Access-Control-Allow-Origin", "*");
    next();
})