• Spring-Cloud GateWay+Vue 跨域方案汇总


    一、简介

    背景和概述

    在开发Spring Cloud和Vue的项目时,涉及到前后端分离的情况下,跨域成为一个常见的问题。本文将介绍跨域问题的背景,并提供了一些解决方案。
    在这里插入图片描述

    二、前端跨域解决方案

    Axios跨域

    Axios是一个流行的基于Promise的HTTP客户端,用于浏览器和Node.js。它可以使发送HTTP请求变得更加简单和高效。
    一般前端使用axios进行http请求发送

    import axios from 'axios'
    // 利用axios对象的方法create,创建一个axios实例
    const request = axios.create({
        baseURL: "http://localhost:8080",
        timeout: 3000000, //请求超时的时间
        withCredentials: true, // 打开withCredentials选项
        crossDomain: true,
    })
    
    // request 请求拦截器,在发请求之前,请求拦截器可以检测到
    //config:配置对象,里面有一个属性是headers请求头
    request.interceptors.request.use(config => {
    	  // 设置允许跨域的域名和请求方法
    	  config.headers['Access-Control-Allow-Origin'] = '*';
    	  config.headers['Access-Control-Allow-Methods'] = 'GET, POST, PUT, DELETE';
        return config
    }, error => {
        return Promise.reject(error)
    });
    
    // response 响应拦截器
    request.interceptors.response.use(
        //响应成功回调函数
        response => {
            let res = response.data;
            return res;
        },
        //响应失败的回调函数
        error => {
            Toast.clear()
            console.log('err' + error)
            return Promise.reject(error)
        }
    )
    
    // 对外暴露
    export default request
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37

    CORS跨域

    CORS(Cross-Origin Resource Sharing)是一种跨域访问资源的标准,可以通过在服务器端设置响应头来实现跨域请求。以下是CORS的示例代码:

    // 在后端Spring MVC控制器中配置CORS
    @CrossOrigin
    @RestController
    @RequestMapping("/api")
    public class MyController {
        // 控制器的方法
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    三、后端跨域解决方案

    反向代理服务器

    使用反向代理服务器可以将前端请求转发到后端服务器,从而绕过跨域限制。以下是反向代理服务器的示例代码:
    这里nginx是要和你的前端服务在一台服务器上的,然后你访问的时候通过前端的nginx进行转发的后端服务器才行

    # NGINX反向代理配置示例
    location /api {
        proxy_pass http://backend-server;
    }
    
    • 1
    • 2
    • 3
    • 4

    四、Spring Cloud中的跨域解决方案

    Gateway网关的跨域配置

    整个项目中只需要配置网关的配置文件即可,其他地方(前后端)都不需要在进行更改
    在Spring Cloud中使用Gateway作为网关时,可以通过配置来处理跨域请求。以下是Gateway网关的跨域配置的示例代码:

    # 在Gateway网关中配置跨域
    spring:
      cloud:
        gateway:
          globalcors:
            cors-configurations:
              '[/**]':
                allowedOrigins: "*"
                allowedHeaders: "*"
                allowedMethods: "*"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    五、基于Vue和Spring Cloud的跨域整合实践

    这两种配置只需配置一种即可生效(前端or后端)

    前端Vue项目配置

    在Vue项目中进行跨域配置,确保前端请求能够访问后端服务。以下是前端Vue项目配置的示例代码:
    参考:Vue官方文档

    // 在Vue项目的配置文件中设置代理
    module.exports = {
      devServer:{
        proxy:{
          '/getTest':{
            target:"http://localhost:7734",  //跨域的域名(不需要写路径)
            changeOrigin:true,//是否开启跨域
            // pathRewrite:{  //路径重写
            //
            // }
          }
        }
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    后端Spring Cloud项目配置

    这是一种方案,还可以使用上面说的gateway配置文件的方式,这两种二选一
    在Spring Cloud项目中进行跨域配置,确保后端能够处理前端请求。以下是后端Spring Cloud项目配置的示例代码:

    import com.alibaba.nacos.shaded.com.google.common.net.HttpHeaders;
    import org.springframework.cloud.gateway.filter.GatewayFilterChain;
    import org.springframework.cloud.gateway.filter.GlobalFilter;
    import org.springframework.core.annotation.Order;
    import org.springframework.stereotype.Component;
    import org.springframework.web.server.ServerWebExchange;
    import reactor.core.publisher.Mono;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Collectors;
    // 在后端Spring Cloud-GateWay中配置跨域
    @Component
    @Order(2)
    public class CorsResponseHeaderFilter implements GlobalFilter {
    
    
        private static final String ANY = "*";
    
    
        @Override
        @SuppressWarnings("serial")
        public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
            return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                exchange.getResponse().getHeaders().entrySet().stream()
                        .filter(kv -> (kv.getValue() != null && kv.getValue().size() > 1))
                        .filter(kv -> (kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN)
                                || kv.getKey().equals(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS)
                                || kv.getKey().equals(HttpHeaders.VARY)))
                        .forEach(kv ->
                        {
                            // Vary只需要去重即可
                            if(kv.getKey().equals(HttpHeaders.VARY)) {
                                kv.setValue(kv.getValue().stream().distinct().collect(Collectors.toList()));
                            } else{
                                List<String> value = new ArrayList<>();
                                if(kv.getValue().contains(ANY)){  //如果包含*,则取*
                                    value.add(ANY);
                                    kv.setValue(value);
                                }else{
                                    value.add(kv.getValue().get(0)); // 否则默认取第一个
                                    kv.setValue(value);
                                }
                            }
                        });
            }));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    六、总结

    跨域(Cross-Origin Resource Sharing,CORS)是一种浏览器的安全机制,用于限制从一个源(域、协议或端口)加载的Web页面上的资源如何与来自其他源的资源进行交互。当一个 Web 应用程序尝试从一个源加载来自不同源的资源时,浏览器将执行跨域检查。

    跨域限制的目的是保护用户隐私和安全,防止恶意网站通过跨域请求来获取用户的敏感信息。如果跨域是允许的,那么一个恶意网站就可以在用户不知情的情况下获取到来自其他网站的数据,这将带来安全风险。

    在默认情况下,浏览器会限制跨域请求,例如,从一个域(例如example.com)的页面发起的 AJAX 请求无法直接访问另一个域(例如api.example.com)的资源。这是因为浏览器执行了同源策略(Same-Origin Policy),即只允许在同一个域下加载资源。

    为了解决跨域问题,可以使用 CORS 机制来明确指示浏览器允许跨域请求。服务器可以在响应中添加一些特殊的头部(如 “Access-Control-Allow-Origin”)来指定允许访问的来源,即允许跨域请求的网站。

    需要注意的是,跨域问题仅存在于浏览器环境中。如果是在服务器之间进行通信,不受同源策略的限制,可以通过其他方式(如代理、反向代理)来实现跨域请求。

    总结而言,跨域限制是为了保护用户隐私和安全,防止恶意网站获取敏感信息。使用 CORS 机制可以显式指示浏览器允许跨域请求。

  • 相关阅读:
    蓝桥杯官网练习题(算式900)
    前端——Vuex状态管理
    Mysql根据经纬度查询半径多少以内的数据,画个圈圈查数据库
    解决问题error: reference to ‘byte‘ is ambiguous
    java中的并发工具类
    【Spring Boot】Spring Boot集成RabbitMQ
    二三里APP逆向- 国庆篇
    机器学习笔记 九:预测模型优化(防止欠拟合和过拟合问题发生)
    35【源码】数据可视化:基于 Echarts + Python 动态实时大屏 - 门店销售业绩数据中心
    13 | 集合中泛型
  • 原文地址:https://blog.csdn.net/pengjun_ge/article/details/132808411