SpringCloudGateway配置跨域设置以及如何本地测试跨域

问题背景

有个服务A ,自身对外提供服务,几个系统的前端页面也在调用,使用springboot 2.6.8开发的,自身因为有前端直接调用已经配置了跨域。

现在有网关服务,一部分前端通过网关访问服务A(因为之前没有网关服务,这里不解释为何以前没有,总之大家在工作中会遇到各种各项的系统设计 或者部署 或者使用的hack, 老旧系统又不能随便改动,主要涉及的使用方较多,很难协调他们统一改动)。 网关使用的SpringCloudGateway ( 实际的gateway版本是3.1.3 webflux 2.7.8), 网络服务也配置跨域,但是一些系统的前端通过网关调用A的时候包跨域有问题。

前端浏览器中错误信息, 这里省略其他无关域名和ip内容,只保留错误的主要信息

Access-Control-Allow-Origin’ header contains multiple values’, but only one is allowed 

简要分析

两个服务都已经配置了跨域,直接访问网关自身的一些API (例如health check的api)都正常,但是通过网关访问服务A就有问题, 一看是因为两个都配置了跨域,直接取消服务A的跨域配置,错误会消息,但是因为一部分前端是直接调用A服务的,因为A服务自身的跨域设置不能取消。 只能在网关处更改。 最终就是将网关处从A返回的response header进行去重,满足需求。

解决办法

在gateway配置的RouteLocator修改如下, 备注:也可以通过配置文件实现,本人采用代码的方式。 这是可以工作的示例代码,其中svcaBaseUrl,serverPort需要再配置文件中对应的值,这两个也是A服务的域名, 以及网关服务的端口。

备注:其他人也遇到同样问题, 参看:https://stackoverflow.com/questions/70983244/use-spring-gateway-and-getting-error-access-control-allow-origin-header-conta。 本文方法仅供参考

@Component
public class MyRouteLocator
{
  @Value("${svca.baseUrl}")
  String svcaBaseUrl;

  @Value("${server.port}")
  int serverPort;

  @Bean
  public RouteLocator myRoutes(RouteLocatorBuilder builder)
  {
    return builder.routes()
      .route(p -> p
        .path("/proxy/version/query-by-id", "/proxy/version/status", "/health",
          "/proxy/version/add",)
        .filters(f ->  f.stripPrefix(1).dedupeResponseHeader("Access-Control-Allow-Origin", RETAIN_UNIQUE.name()))
        .uri(svcaBaseUrl))
   
          
      .route(p -> p
        .path("/proxy/version/*","/proxy/log/*")
        .filters(f ->  f.stripPrefix(1))
        .uri("http://127.0.0.1:%d/notSupport".formatted(serverPort)))
      .build();
  }
}

网关跨域配置 MyConfig.java, 备注:这只是全局配置跨域一种方式,可以在api单独配置。此处不在赘述。可以参考其他网络如何给springboot程序配置跨域设置。

package x.y.proxy;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@Configuration
public class MyConfig {
  @Bean
  CorsWebFilter corsFilter() {

    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOriginPattern("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", config);

    return new CorsWebFilter(source);
  }

}

服务A是springboot 2.6.8, 跨域配置如下

  @Bean
  public WebMvcConfigurer webMvcConfigurer()
  {
    return new WebMvcConfigurer()
    {
      @Override
      public void addCorsMappings(CorsRegistry registry)
      {
        registry.addMapping("/**") 
          .allowedOriginPatterns("*") 
          .allowedHeaders("*") 
          .allowedMethods("*") 
          .allowCredentials(true) 
          .maxAge(TimeUnit.DAYS.toSeconds(1));
      }
    };
  }

本地浏览器中验证跨域问题

跨域问题是前端发现的,后端开发可以在chrome浏览器中直接测试验证,不需要前端同学配置,可以加速开发过程

//  测试post方法使用 a.b.c是需要替换的域名 或者ip
:var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://a.b.c/version/add?Id=2&label=test1');
xhr.setRequestHeader("Content-type","application/json;charset=UTF-8");
xhr.setRequestHeader("jwt-token","JhbGciOiJSUzI1N");
xhr.setRequestHeader("x-access-token","aaa");
xhr.send('{"version": "1.0","desc": "string"}');
xhr.onload = function(e) {
   var xhr = e.target;
   console.log(xhr.responseText);
}

//  测试get方法使用 a.b.c是需要替换的域名 或者ip
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://a.b.c/common/health');
xhr.setRequestHeader("x-access-token","aaa");
xhr.setRequestHeader("Access-Control-Allow-Origin","bbb");
xhr.setRequestHeader("Content-type","application/json;charset=UTF-8");
xhr.send(null);
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

执行console测试示意图

在这里插入图片描述

备注:这里附录上网关工程的一些gradle信息,如果你使用的gateway版本与我不一样,请以对应版本的官方文档为准

例如我使用gateway 3.1.3 cors配置文件如下:
https://docs.spring.io/spring-cloud-gateway/docs/3.1.3/reference/html/#cors-configuration

plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.8'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.x.y'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
	compileOnly {
		extendsFrom annotationProcessor
	}
}

repositories {
	mavenCentral()
}

ext {
	set('springCloudVersion', "2021.0.3")
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-webflux'
	implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
	implementation 'org.springdoc:springdoc-openapi-ui:1.6.11'
	implementation 'io.netty:netty-all:4.1.75.Final'
	compileOnly 'org.projectlombok:lombok'
	annotationProcessor 'org.projectlombok:lombok'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'io.projectreactor:reactor-test'
}

dependencyManagement {
	imports {
		mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
	}
}

tasks.named('test') {
	useJUnitPlatform()
}
bootJar {
	archiveBaseName = 'app'
	def excludes = [~"junit.*\\.jar", ~"hamcrest.*\\.jar"]
	exclude {
		for (exclude in excludes) {
			if (it.name ==~ exclude) {
				return true
			}
		}
		return false
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/71415.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

springboot 基础

巩固基础,砥砺前行 。 只有不断重复,才能做到超越自己。 能坚持把简单的事情做到极致,也是不容易的。 SpringBoot JavaEE 简介 JavaEE的局限性: 1、过于复杂,JavaEE正对的是复杂的分布式企业应用,然而现实…

桥接模式-java实现

桥接模式 桥接模式的本质,是解决一个基类,存在多个扩展维度的的问题。 比如一个图形基类,从颜色方面扩展和从形状上扩展,我们都需要这两个维度进行扩展,这就意味着,我们需要创建一个图形子类的同时&#x…

软件测试基础篇——MySQL

MySQL 1、数据库技术概述 数据库database:存放和管理各种数据的仓库,操作的对象主要是【数据data】,科学的组织和存储数据,高效的获取和处理数据SQL:结构化查询语言,专为**关系型数据库而建立的操作语言&…

科技云报道:一波未平一波又起?AI大模型再出邪恶攻击工具

AI大模型的快速向前奔跑,让我们见识到了AI的无限可能,但也展示了AI在虚假信息、深度伪造和网络攻击方面的潜在威胁。 据安全分析平台Netenrich报道,近日,一款名为FraudGPT的AI工具近期在暗网上流通,并被犯罪分子用于编…

基于微信小程序的应届大学生招聘平台的设计与实现

伴随着社会以及科学技术的发展,互联网已经渗透在人们的身边,网络慢慢的变成了人们的生活必不可少的一部分,紧接着众多智能手机飞速的发展,小程序这一名词已不陌生,越来越多的企业、公司、高校、医院等机构都会使用小程…

C++学习笔记——从面试题出发学习C++

C学习笔记——从面试题出发学习C C学习笔记——从面试题出发学习C1. 成员函数的重写、重载和隐藏的区别?2. 构造函数可以是虚函数吗?内联函数可以是虚函数吗?析构函数为什么一定要是虚函数?3. 解释左值/右值、左值/右值引用、std:…

Clickhouse学习系列——一条SQL完成gourp by分组与不分组数值计算

笔者在近一两年接触了Clickhouse数据库,在项目中也进行了一些实践,但一直都没有一些技术文章的沉淀,近期打算做个系列,通过一些具体的场景将Clickhouse的用法进行沉淀和分享,供大家参考。 首先我们假设一个Clickhouse数…

EXPLAIN使用分析

系列文章目录 文章目录 系列文章目录一、type说明二、MySQL中使用Show Profile1.查看当前profiling配置2.在会话级别修改profiling配置3.查看profile记录4.要深入查看某条查询执行时间的分布 一、type说明 我们只需要注意一个最重要的type 的信息很明显的提现是否用到索引&…

单参数构造函数的隐式类型转化

单参数构造函数的隐式类型转化 如果你不想发生隐式类型的转化,可以在默认构造函数前加上关键字:explicit 多参数的玩法和单参数的是不一样的 c98 不支持多参数隐式类型的转化 c11 支持多参数隐式类型的转化 举个例子: 多参数可以这样写&…

考虑分布式电源的配电网无功优化问题研究(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

计算机视觉中的Transformer

几十年来,理论物理学家一直在努力提出一个宏大的统一理论。通过统一,指的是将被认为是完全不同的两个或多个想法结合起来,将它们的不同方面证明为同一基础现象。一个例子是在19世纪之前,电和磁被看作是无关的现象,但电…

SolidWorks不能使用选择如允许此选择将生成有冲突的前后关系

SolidWorks不能使用选择如允许此选择将生成有冲突的前后关系 1 SolidWorks不能使用选择如允许此选择将生成有冲突的前后关系 1 SolidWorks不能使用选择如允许此选择将生成有冲突的前后关系 https://www.swrjzxw.com/1556.html SolidWorks装配体时 显示 不能使用选择如允许此选…

CSS 中的优先级规则是怎样的?

聚沙成塔每天进步一点点 ⭐ 专栏简介⭐内联样式(Inline Styles)⭐ID 选择器(ID Selectors)⭐类选择器、属性选择器和伪类选择器(Class, Attribute, and Pseudo-class Selectors)⭐元素选择器和伪元素选择器…

2023.8.12号论文阅读

文章目录 TriFormer: A Multi-modal Transformer Framework For Mild Cognitive Impairment Conversion Prediction摘要本文方法实验结果 SwIPE: Efficient and Robust Medical Image Segmentation with Implicit Patch Embeddings摘要本文方法实验结果 TriFormer: A Multi-mod…

服务器安装Tomcat

下载Tomcat 下载地址在这: Tomcat官网 下载完成以后把压缩包上传到服务器中(我传到了www/java),进行解压(解压到),如果没有进行指定解压到哪里,默认是到root文件夹中 tar -zxvf /www/java/apache-tomcat-9.0.103.tar.…

掌握Python的X篇_32_使用python编辑pdf文件_pdfrw

本篇介绍利用python操作pdf文件,我们平时也会有合并和拆分pdf的需求,此时我们就可以使用本节内容。 文章目录 1. pdfrw的安装2. 切分pdf文件3. pdfrw官网及实现一版四面的实例 1. pdfrw的安装 pip install pdfrw官网地址:https://github.co…

QT之UDP通信

QT之UDP通信 UDP不分客户端口服务器,只需要使用一个类QUdpSocket QT += core gui networkgreaterThan(QT_MAJOR_VERSION, 4): QT += widgetsTARGET = udp TEMPLATE = app# The following define makes your compiler emit warnings if you use # any feature of Qt …

使用Openoffice或LibreOffice实现World、Excel、PPTX在线预览

使用Openoffice或LibreOffice实现World、Excel、PPTX在线预览 预览方案使用第三方服务使用前端库转换格式 jodconverterjodconverter概述主要特性OpenOfficeLibreOffice jodconverter的基本使用添加依赖配置创建DocumentConverter实例上传与转换预览启动上传与预览World 与Spri…

C#应用处理传入参数 - 开源研究系列文章

今天介绍关于C#的程序传入参数的处理例子。 程序的传入参数应用比较普遍,特别是一个随操作系统启动的程序,需要设置程序启动的时候不显示主窗体,而是在后台运行,于是就有了传入参数问题,比如传入/h或者/min等等。所以此…

配置vscode

配置vscode 设置相关 网址:https://code.visualstudio.com/ 搜索不要用百度用这个:cn.bing.com 1.安装中文包 Chinese (Simplified) (简体中文) 2.安装 open in browser 3.安装主题 Atom One Dark Theme 4. 安装图标样式 VSCode Great Icons 5.安装 L…