zoukankan      html  css  js  c++  java
  • 前端跨域解决方案--代理

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

    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 来实现跨域的配置是最简单的、成本最低的一种解决方案,也是我平时开发中用的最多的,这里比较推荐。

  • 相关阅读:
    Spring Boot 7:配置文件信息读取
    Spring Boot 6:自定义filter
    Spring AOP:Java动态代理和CGlib
    Spring AOP:概念
    设计模式(二)---策略模式
    设计模式(一)--装饰模式
    java并发编程实战笔记
    剑指offer java -查找旋转数组的最小数字
    读书计划
    协议初学
  • 原文地址:https://www.cnblogs.com/cmyoung/p/13498845.html
Copyright © 2011-2022 走看看