前端跨域解决方案--代理

代理服务器监听本地请求,然后由代理服务器转发请求到目标服务器,因为服务端不存在同源策略,所以不存在跨域问题。

1. webpack-dev-server

项目如果有使用 webapck 的开发服务器,那么只需要配置一下代理(proxy)就可以轻松实现跨域,如下

``` 
devServer: {
  contentBase: [
    path.join(__dirname, '../public'),
    path.join(__dirname, '..')
  ],
  hot: true,
  host: '0.0.0.0',
  disableHostCheck: true,

  // 代理相关
  proxy: {
    '/api/**': { // 匹配代理路径规则,仅代理接口请求,页面和静态资源请求不需要
      target: 'http://test.com', // 后端提供的目标接口地址
      pathRewrite: {'^/api': ''}, // 重写路径
      secure: false, // 接受 运行在 https 上的服务
      changeOrigin: true // 默认false,是否需要改变原始主机头为目标URL
    }
  }
}

```

2. node.js

http-proxy-middleware 中间件实际就是将 http-proxy 封装,使用起来更加方便简单。

``` 

const express = require('express');
const app = express();
const { createProxyMiddleware } = require('http-proxy-middleware');

const port = 8888; // 代理服务端口

app.use('/', createProxyMiddleware({
    // 代理跨域目标接口
    target: 'http://test.com',
    changeOrigin: true,
    // pathRewrite: {
    //     '^/api' : '/',     // 重写请求
    // },
    // 修改响应头信息,实现跨域并允许带cookie
    onProxyRes: function(proxyRes, req, res) {
        const origin = req.headers.origin || '*'  // 当前端只跨域不带cookie时,可为*
        res.header('Access-Control-Allow-Origin', origin); 
        res.header('Access-Control-Allow-Credentials', 'true'); //  它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
    }
}));

app.listen(port);
console.log(`Proxy server is listen at port ${port}...`);

```

3. nginx

1). 浏览器请求 nginx, 然后 nginx 代理去访问前端资源和后端接口,因为对于浏览器来说,接口和页面是同一个域名和端口,而服务端又不存在跨域,从而实现跨域访问。

    #proxy 服务器 配置
    server {
      listen       8888;
      server_name  localhost;

      location / { 
         proxy_pass http://localhost:8080; # 除localhost:8888/api/ 外的其他请求代理到 localhost:8080 (前端自己的服务)
      }

      location /api/ {
         proxy_pass http://test.后端接口.com; # 将 localhost:8888/api/ * 请求代理到了http://test.后端接口.com; (后端接口服务器)
      }
    }

2). nginx 仅代理后端接口地址,设置为允许所有的 域请求或允许前端的域请求。实质和CORS跨域原理一样,通过配置文件设置请求响应头Access-Control-Allow-Origin...等字段。

    #proxy 服务器 配置
    server {
      listen       8888;
      server_name  localhost;

      location / {
          root   html;
          index  index.html index.htm;
      }

      location /api/ {  # 当请求为 localhost:8888/api/* 时,  代理转发到 http://test.后端接口.com/api/* 
          proxy_pass   http://test.后端接口.com;  # 后端目标服务器
          add_header Access-Control-Allow-Origin http://localhost:8888;  #当前端只跨域不带cookie时,可设置为 *
          add_header Access-Control-Allow-Credentials true;
      }
    }

4. 猜想

看到这里,也许你的心里会有疑问,既然 nginx 可以有两种实现的思路,那么前面的 webpack 和 node.js 应该也可以做到啊,因为他们在这里都是作为代理服务器使用的啊?
恭喜你猜对了,答案是:可以的。
对于 node.js 和 webpack 的开发服务器,我们同样可以实现,既代理静态资源又代理后端接口的方案,简单说:就是让浏览器的所有请求都走代理服务器,根据不同的请求规则,由代理服务器去匹配对应的资源或接口

比如,下面的 node.js 方案:

const express = require('express');
const app = express();
const { createProxyMiddleware } = require('http-proxy-middleware');

const port = 8888;

app.use('/html', createProxyMiddleware({  // 当浏览器访问 localhost:8888/html/ 时,匹配的是前端资源
    target: 'http://0.0.0.0:8082', // 前端资源地址
    changeOrigin: true,
    pathRewrite: {
        '^/html' : '/',     // 重写请求
    }
}));

app.use('/api', createProxyMiddleware({ // 当浏览器访问 localhost:8888/api/ 时,匹配的是接口地址
    // 代理跨域目标接口
    target: 'https://test.接口.com',
    changeOrigin: true,
    pathRewrite: {
        '^/api' : '/',     // 重写请求
    },
    // 修改响应头信息,实现跨域并允许带cookie
    onProxyRes: function(proxyRes, req, res) {
        const origin = req.headers.origin || '*'
        res.header('Access-Control-Allow-Origin', origin); 
        res.header('Access-Control-Allow-Credentials', 'true');
    }
}));

app.listen(port);

5.最后

总结: 相对来说,使用 webpack 来实现跨域的配置是最简单的、成本最低的一种解决方案,也是我平时开发中用的最多的,这里比较推荐。

posted @ 2020-08-24 21:42  cmyoung  阅读(3099)  评论(0编辑  收藏  举报