SpringCloud微服务中跨域配置的方法详解

跨域,指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对 javascript 施加的安全限制。

同源策略,指的是协议,域名,端口都要相同,其中有一个不同都会产生跨域。

跨域相关含义:

  • Access-Control-Allow-Origin:服务器允许请求的源;
  • Access-Control-Allow-Headers: 服务器允许使用的头;
  • Access-Control-Allow-Methods: 真实请求允许的方法;
  • Access-Control-Allow-Credentials: 是否允许用户发送、处理 cookie;
  • Access-Control-Max-Age: 预检请求的有效期,单位为秒。有效期内,不会重复发送预检请求;

Java微服务中解决跨域问题主要分为如下情况:

情况1:针对单个服务的跨域问题,增加允许跨域配置类即可。

如,前端vue+业务微服务

情况2:有网关时,网关配置允许跨域,微服务不配置。微服务项目网关服务为Spring Cloud Gateway,则要求所有请求统一走网关,无需给每个微服务都配置跨域,只需要给网关微服务gateway配置跨域即可。

如,前端vue+网关服务gateway+业务微服务

情况3:有网关时,网关配置允许跨域,微服务配置允许跨域。需要在网关的配置里加上重复请求头。配置DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_UNIQUE。此时走不走网关,都没有跨域问题。

如,前端vue+网关服务gateway+业务微服务/认证授权微服务

情况4:网关不配置,微服务配置允许跨域。请求如果走网关,则会存在跨域问题。不走网关,直接访问微服务,没有跨域问题。

情况5:网关不配置,微服务不配置。走不走网关都会存在跨域问题。

情况1

单个springboot微服务的跨域配置如下

若springboot版本为2.4.0以前,则设置请求源为

corsConfiguration.addAllowedOrigin(“*”);

若springboot版本为2.4.0以后,则设置请求源为

corsConfiguration.setAllowedOriginPatterns(Collections.singletonList(“*”));

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        // 跨域配置源
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        //设置跨域的配置信息
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        //1,允许任何来源
        corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
        //2,允许任何请求头
        corsConfiguration.addAllowedHeader(CorsConfiguration.ALL);
        //3,允许任何方法
        corsConfiguration.addAllowedMethod(CorsConfiguration.ALL);
        //4,允许凭证
        corsConfiguration.setAllowCredentials(true);
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter(source);
    }
}

其中,若在springboot2.3.10版本中使用corsConfiguration.addAllowedOrigin(“*”);是可以解决跨域问题的,若在springboot2.7.0版本中使用,会发现报跨域问题,查看后台日志提示如下异常:

When allowCredentials is true, allowedOrigins cannot contain the special value "*"since that cannot be set on the “Access-Control-Allow-Origin” response header. To allow credentials to a set of origins, list them explicitly or consider using “allowedOriginPatterns” instead.

可见,不能在 corsConfiguration.setAllowCredentials(true)的时候对addAllowedOrigin设置为"*",而要使用 allowedOriginPatterns这个字段来设置origin。

其实,也可以采用重写WebMvcConfigurer的方式或使用注解@CrossOrigin的方式。

情况2

gateway网关服务中跨域配置类如下

若springboot版本为2.4.0以前,则设置请求源为

corsConfiguration.addAllowedOrigin(“*”);

若springboot版本为2.4.0以后,则设置请求源为

corsConfiguration.setAllowedOriginPatterns(Collections.singletonList(“*”));

@Configuration
public class CorsConfig {
    @Bean
    public CorsWebFilter corsFilter() {
        // 跨域配置源
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        //设置跨域的配置信息
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        // 允许所有请求来源进行跨域
        //corsConfiguration.addAllowedOrigin("*");
        // spring boot2.4以后的配置
        corsConfiguration.setAllowedOriginPatterns(Collections.singletonList("*"));
        // 允许所有头进行跨域
        corsConfiguration.addAllowedHeader("*");
        // 允许所有请求方式进行跨域
        corsConfiguration.addAllowedMethod("*");
        // 允许携带cookie进行跨域
        corsConfiguration.setAllowCredentials(true);
        //任意路径都需要跨域配置
        source.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsWebFilter(source);
    }
}

注:需要去掉业务微服务的跨域配置,防止多次跨域配置。

其实,也可以采用在gateway网关服务的application.yml文件中配置的方式,如:

spring:
  cloud:
    gateway:
      # 全局的跨域配置
      globalcors:
        # 解决options请求被拦截问题
        add-to-simple-url-handler-mapping: true
        cors-configurations:
          # 拦截的请求
          '[/**]':
            # 允许跨域的请求
            #allowedOrigins: "*" # spring boot2.4以前的配置
            allowedOriginPatterns: "*" # spring boot2.4以后的配置
            # 允许请求中携带的头信息
            allowedHeaders: "*"
            # 运行跨域的请求方式
            allowedMethods: "*"
            # 是否允许携带cookie
            alloweCredentials: true
            # 跨域检测的有效期,单位s
            maxAge: 36000

不要出现重复解决跨域问题,若之前用过注解@CrossOrigin,然后又添加了过滤器,就会导致重复,仅用过滤器就OK了。

情况3

当gateway网关服务设置了跨域,业务微服务也设置了跨域,则需要在网关的配置里加上重复请求头,如

pring:
  cloud:
    gateway:
      globalcors:
        default-filters:
                - DedupeResponseHeader=Vary Access-Control-Allow-Origin Access-Control-Allow-Headers Access-Control-Allow-Credentials,RETAIN_UNIQUE

当业务微服务集成了security+oauth2,会出现跨域失效的情况,需要在WebSecurityConfig配置类和ResourceServerConfig配置类中开启CORS,如下

	@Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .csrf().disable();
    }
	@Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .cors()
                .and()
                .csrf().disable();
     }

当gateway网关微服务集成了security+oauth2,又会出现跨域问题,则需要在ResourceServerConfig配置类中加入跨域过滤器,如下

	@Bean
    public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) throws NoSuchAlgorithmException, IOException, InvalidKeySpecException {
        http.cors().and().csrf().disable();
		http.addFilterBefore(corsWebFiler, SecurityWebFiltersOrder.CORS);
	}

跨域问题:The ‘Access-Control-Allow-Origin’ header contains multiple values “*, *”, but only one is allowed.

分析:通常跨域问题可以在三个地方解决:

  • 在微服务的代码中通过跨域配置类解决;
  • 在网关中解决,可以通过配置类,也可以通过yml配置;
  • 在nginx或vue中解决;

以上3种方式,若使用了2种,则会出现双重跨域的问题。那么若是知道那里用了2次跨域配置,选择去掉一个即可;若是2个地方都不想去掉,还可以在网关中通过yml配置来忽略掉双重跨域的问题。

spring:
  main:
    allow-bean-definition-overriding: true
    gateway:
      discovery:  默认为false,设为true便开启通过服务中心的自动根据 serviceId 创建路由的功能。
        locator:  
          enabled: true
          lowerCaseServiceId: true
      #解决跨域问题
      globalcors:
        corsConfigurations:
          '[/**]':
            # 允许携带认证信息
            allow-credentials: true
            # 允许跨域的源(网站域名/ip),设置*为全部
            allowedOrigins: "*"
            # 允许跨域的method, 默认为GET和OPTIONS,设置*为全部
            allowedMethods: "*"
            # 允许跨域请求里的head字段,设置*为全部
            allowedHeaders: "*"
      #解决双重跨域 RETAIN_FIRST RETAIN_LAST RETAIN_UNIQUE
      default-filters:
        - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials Vary, RETAIN_UNIQUE

具体跨域问题还需根据具体情况分析解决。

到此这篇关于SpringCloud微服务中跨域配置的方法详解的文章就介绍到这了,更多相关SpringCloud跨域配置内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringCloud微服务续约实现源码分析详解

    目录 一.前言 二.客户端续约 1.入口 构造初始化 initScheduledTasks()调度执行心跳任务 2.TimedSupervisorTask组件 构造初始化 TimedSupervisorTask#run()任务逻辑 3.心跳任务 HeartbeatThread私有内部类 发送心跳 4.发送心跳到注册中心 构建请求数据发送心跳 三.服务端处理客户端续约 1.InstanceRegistry#renew()逻辑 2.PeerAwareInstanceRegistryImpl#rene

  • SpringCloud微服务剔除下线功能实现原理分析

    目录 一.前言 二.微服务剔除下线源码解析 1.EurekaBootStrap#contextInitialized() 1.1.初始化注册中心上下文 1.2.openForTraffic()逻辑 1.3.postInit()执行任务 1.4.剔除任务 2.服务剔除下线 2.1.AbstractInstanceRegistry#evict()逻辑 2.1.判断是否过期 2.2.从本地列表异常下线处理 一.前言 上一篇SpringCloud微服务续约源码解析已经分析了心跳机制是什么.底层实现.客户

  • SpringCloud超详细讲解微服务网关Zuul基础

    目录 一.Zuul的简介 1.Zuul是怎么工作的 2.Zuul能干嘛 二.Zuul的使用 1.配置Pom.xml 2.配置Application.yml 3.撰写启动类 4.效果图 三.学会SpringCloud的感触 一.Zuul的简介 1.Zuul是怎么工作的 Zull包含了对请求的路由(用来跳转的)和过滤两个最主要功能: 其中路由功能负责将外部请求转发到具体的微服务实例上,是实现外部访问统一入口的基础,而过滤器功能则负责对请求的处理过程进行干预,是实现请求校验,服务聚合等功能的基础.Zu

  • SpringCloud微服务的调用与远程调用测试示例

    目录 微服务相关简述 微服务架构中的重要角色 微服务架构 分布式远程调用 RESTFUL接口 资源 表现层 状态转化 RPC CAP原理 springCloud简述 服务注册与发现 负载均衡 熔断 链路追踪 API网关 测试模拟远程调用 创建父工程remote_call模块 创建子模块server_a 创建子模块server_b 微服务相关简述 微服务架构中的重要角色 服务调用者:可以暂时认为是与用户交互的角色(因为存在微服务之间的调用),可以根据该用户的类型将其赋予不同的服务调用权限,通过一次

  • springcloud微服务之Eureka配置详解

    Eureka注册中心/服务发现框架 Eureka是Netflix开发的服务发现框架,本身是一个基于REST的服务,主要用于定位运行在AWS域中的中间层服务,以达到负载均衡和中间层服务故障转移的目的.SpringCloud将它集成在其子项目spring-cloud-netflix中,以实现SpringCloud的服务发现功能. Eureka包含两个组件:Eureka Server和Eureka Client. Eureka Server提供服务注册服务,各个节点启动后,会在Eureka Serve

  • SpringCloud微服务应用config配置中心详解

    目录 前言 一.传统应用配置痛点 二.Config 配置中心介绍 三.服务端Config Server搭建 1.pom依赖 2.application启动类配置 3.application.yml配置 4.test-dev.xml(客户端应读取的配置) 5.项目结构 四.客户端Config Client搭建 1.pom依赖 2.application启动类配置 3.bootstrap.yml配置 4.application.yml配置 5.测试controller 6.项目结构 五.动态刷新 六

  • SpringCloud实现文件上传功能的方法详解

    目录 图片上传 搭建项目 编写上传功能 图片上传 刚才的新增实现中,我们并没有上传图片,接下来我们一起完成图片上传逻辑. 文件的上传并不只是在品牌管理中有需求,以后的其它服务也可能需要,因此我们创建一个独立的微服务,专门处理各种上传. 搭建项目 创建SpringCloud项目 添加依赖 我们需要EurekaClient和web依赖: <?xml version="1.0" encoding="UTF-8"?> <project xmlns=&quo

  • Java JWT实现跨域身份验证方法详解

    目录 1.JWT简介 2.JWT的结构 2.1 头部(header) 2.2 载荷(payload) 2.3 签证(signature) 3.JWT的原则 4.JWT的用法 5.JWT的问题和趋势 6.整合JWT令牌 6.1 在模块中添加jwt工具依赖 6.2 创建JWT工具类 1.JWT简介 JWT(JSON Web Token)是目前流行的跨域认证解决方案,是一个开放标准(RFC 7519),它定义了一种紧凑的.自包含的方式,用于作为JSON对象在各方之间安全地传输信息.该信息可以被验证和信

  • struts2中使用注解配置Action方法详解

    使用注解来配置Action可以实现零配置,零配置将从基于纯XML的配置转化为基于注解的配置.使用注解,可以在大多数情况下避免使用struts.xml文件来进行配置. struts2框架提供了四个与Action相关的注解类型,分别为ParentPackage.Namespace.Result和Action. ParentPackage:ParentPackage注解用于指定Action所在的包要继承的父包.该注解只有一个value参数.用于指定要继承的父包. 示例: 使用ParentPackage

  • C#设置或验证PDF文本域格式的方法详解

    目录 概述 引入dll 代码(C#/VB.NET) 概述 PDF中的文本域可以通过设置不同格式,用于显示数字.货币.日期.时间.邮政编码.电话号码和社保号等等.Adobe Acrobat提供了许多固定的JavaScripts用来设置和验证文本域的格式,如:AFNumber_Format(2, 0, 0, 0, "$", true)和AFNumber_Keystroke(2, 0, 0, 0, "$", true).Format后缀的script是用来设置文本域显示的

  • go使用consul实现服务发现及配置共享实现详解

    目录 使用consul四大特性 通过docker安装consul 实现代码 运行结果 使用consul四大特性 1. 服务发现:利用服务注册,服务发现功能来实现服务治理. 2. 健康检查:利用consul注册的检查检查函数或脚本来判断服务是否健康,若服务不存在则从注册中心移除该服务,减少故障服务请求. 3. k/v数据存储:存储kv数据,可以作为服务配置中心来使用. 4. 多数据中心:可以建立多个consul集群通过inter网络进行互联,进一步保证数据可用性. 通过docker安装consul

  • SpringBoot配置绑定方法详解

    目录 配置绑定 @Value基础类型配置 @ConfigurationProperties注解 @PropertySource 配置绑定 所谓“配置绑定”就是把配置文件中的值与 JavaBean 中对应的属性进行绑定.通常,我们会把一些配置信息(例如,数据库配置)放在配置文件中,然后通过 Java 代码去读取该配置文件,并且把配置文件中指定的配置封装到 JavaBean(实体类)中. SpringBoot提供了以下两种方式进行配置绑定: 使用@Value注解 使用@ConfigurationPr

  • 微服务搭建集成Spring Cloud Turbine详解

    1.概述 本文中,我将向你介绍Spring Cloud Netflix Turbine.它将多个Hystrix Metrics Streams 聚合为一个,以便显示在一个仪表板视图中. 简要介绍Hystrix . 在微服务架构中,我们有许多小应用程序相互通信以完成请求.这些下游服务有可能无法正确响应或完全失败.为了防止发生级联故障,我们为微服务设置了Hystrix回退机制. 每个实现Hystrix的微服务都可以选择公开Hystrix Metrics Streams(通过actuator端点/hy

  • Ubuntu中静态DNS配置的方法详解

    DNS服务的简介: DNS(Domain Name Server,域名服务器)是进行域名(domain name)和与之相对应的IP地址 (IP address)转换的服务器.DNS中保存了一张域名(domain name)和与之相对应的IP地址 (IP address)的表,以解析消息的域名. 因为实验室实现的拟态存储系统需要实现动态变更ip地址,所以需要搭建一个dns服务器,并且将需要查询变更ip地址的服务器都绑定到同一台dns服务器之上.通常在RedHat系列(eg:Fedora,Cent

随机推荐