Spring Cloud配置跨域访问的五种方案?你用的是哪一种呢?

在使用SpringCloud实现微服务时,经常会碰到前端页面访问多个二级域名的情况,跨域是首先要解决的问题。

解决这个问题,可以从两方面入手,一种方案是在微服务各自的业务模块中实现,即在SpringBoot层实现,另外一种方案就是在Gateway层实现。

首先讲一下在SpringBoot层实现的三种方案。

解决方案一:在Controller上添加@CrossOrigin注解

这种方式适合只有一两个rest接口需要跨域或者没有网关的情况下,这种处理方式就非常简单,适合在原来基代码基础上修改,影响比较小。

  @CrossOrigin // 注解方式 

  @RestController

   public class HandlerScanController {

        @CrossOrigin(allowCredentials="true", allowedHeaders="*", methods=      {RequestMethod.GET,

  RequestMethod.POST, RequestMethod.DELETE,                                        RequestMethod.OPTIONS,

  RequestMethod.HEAD,

  RequestMethod.PUT,

  RequestMethod.PATCH},

  origins="*")

     @PostMapping("/confirm")

     public Response handler(@RequestBody Request json){

        return null;

       }

  }

解决方案二:增加WebMvcConfigurer全局配置

如果有大量的rest接口的时候,显然第一种方案已经不适合了,工作量大,也容易出错,那就通过全局配置的方式,允许SpringBoot端所有的rest接口都支持跨域访问,这个时候就需要考虑安全性的问题。

代码如下:

@Configuration

public class MyConfiguration {

@Bean

 public WebMvcConfigurer corsConfigurer() {

     return new WebMvcConfigurerAdapter() {

         @Override

          public void addCorsMappings(CorsRegistry registry) {

              registry.addMapping("/**")

              .allowCredentials(true)

              .allowedMethods("GET");

           }

       };

     }

}

解决方案三:结合Filter使用

这种方案的使用场景跟第二种方案类似,只不过换成使用Filter的方式实现。
在spring boot的主类中,增加一个CorsFilter

 /**  

  * attention:简单跨域就是GET,HEAD和POST请求,但是POST请求  的"Content-Type"只能是application/x-www-form-urlencoded, multipart/form-data 或 text/plain 

 * 反之,就是非简单跨域,此跨域有一个预检机制,说直白点,就是会发两次请求,一次OPTIONS请求,一次真正的请求

  */

     @Bean

   public CorsFilter corsFilter() {

        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

       final CorsConfiguration config = new CorsConfiguration();

        config.setAllowCredentials(true); // 允许cookies跨域

        config.addAllowedOrigin("*");// #允许向该服务器提交请求的URI,*表示全部允许,在SpringMVC中,如果设成*,会自动转成当前请求头中的Origin

        config.addAllowedHeader("*");// #允许访问的头信息,*表示全部

        config.setMaxAge(18000L);// 预检请求的缓存时间(秒),即在这个时间段里,对于相同的跨域请求不会再预检了

        config.addAllowedMethod("OPTIONS");// 允许提交请求的方法,*表示全部允许

        config.addAllowedMethod("HEAD");

        config.addAllowedMethod("GET");// 允许Get的请求方法

        config.addAllowedMethod("PUT");

        config.addAllowedMethod("POST"); 

        config.addAllowedMethod("DELETE");

        config.addAllowedMethod("PATCH");

        source.registerCorsConfiguration("/**", config);

        return new CorsFilter(source);

}

以上这种方案如果微服务多的话,需要在每个服务的主类上都加上这么段代码,增加了维护量。

以上三种方案都是在SpringBoot的基础上实现的解决方案,在模块较多或者接口较多的情况下不易维护。

既然SpringCloud自带Gateway,下面就讲讲使用Gateway的跨域解决方案。

解决方案四,在Gateway端增加CorsFilter拦截器

这种方案跟方案三有些类似,只不过是放到了Gateway端,对于有多个微服务模块的情况下,就大大减少了SpringBoot模块端的代码量,让各个模块更集中精力做业务逻辑实现。这个方案只需要在Gateway里添加Filter代码类即可。

public class CorsWebFilter implements WebFilter {

private static final String ALL = "*";

private static final String MAX_AGE = "18000L";

@Override

public Mono<Void> filter(ServerWebExchange ctx, WebFilterChain chain) {

    ServerHttpRequest request = ctx.getRequest();

    String path=request.getPath().value();

    ServerHttpResponse response = ctx.getResponse();

    if("/favicon.ico".equals(path)) {

        response.setStatusCode(HttpStatus.OK);

        return Mono.empty();

    }

    

    if (!CorsUtils.isCorsRequest(request)) {

        return chain.filter(ctx);

    }

    HttpHeaders requestHeaders = request.getHeaders();

    

    HttpMethod requestMethod = requestHeaders.getAccessControlRequestMethod();

    HttpHeaders headers = response.getHeaders();

    headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, requestHeaders.getOrigin());

    headers.addAll(HttpHeaders.ACCESS_CONTROL_ALLOW_HEADERS, requestHeaders.getAccessControlRequestHeaders());

    if (requestMethod != null) {

        headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, requestMethod.name());

    }

    headers.add(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");

    headers.add(HttpHeaders.ACCESS_CONTROL_EXPOSE_HEADERS, ALL);

    headers.add(HttpHeaders.ACCESS_CONTROL_MAX_AGE, MAX_AGE);

    if (request.getMethod() == HttpMethod.OPTIONS) {

        response.setStatusCode(HttpStatus.OK);

        return Mono.empty();

    }

    

    

    return chain.filter(ctx);

}


}

解决方案五,修改Gateway配置文件

在仔细阅读过Gateway的文档你就会发现,原来CorsFilter早已经在Gateway里了,不需要自己写代码实现,而且更灵活,修改配置文件即可,结合配置中心使用,可以实现动态修改。

application.yml.

spring:
cloud:

gateway:      
  globalcors:        
    corsConfigurations:
      '[/**]': 
        allowedOrigins: "docs.spring.io"  
        allowedMethods:
        - GET


以上五种跨域方案讲完了,你用的哪一种呢?还是在自己写代码实现吗?

Spring Cloud Zuul中实现跨域请求可以通过配置Zuul的过滤器来完成。以下是一种常见的实现方式: 1. 创建一个自定义的Zuul过滤器类,实现ZuulFilter接口。可以将该类命名为CorsFilter。 ```java import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants; import org.springframework.stereotype.Component; import com.netflix.zuul.ZuulFilter; import com.netflix.zuul.context.RequestContext; @Component public class CorsFilter extends ZuulFilter { @Override public String filterType() { return FilterConstants.PRE_TYPE; // 在请求被路由之前执行过滤器 } @Override public int filterOrder() { return FilterConstants.PRE_DECORATION_FILTER_ORDER - 1; // 优先级,越小越高 } @Override public boolean shouldFilter() { return true; // 是否执行该过滤器,true表示执行,false表示不执行 } @Override public Object run() { RequestContext context = RequestContext.getCurrentContext(); context.getResponse().addHeader("Access-Control-Allow-Origin", "*"); // 允许跨域访问的域名,*表示所有域名都可以访问 context.getResponse().addHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE"); // 允许的请求方法 context.getResponse().addHeader("Access-Control-Allow-Headers", "Content-Type"); // 允许的请求头 return null; } } ``` 2. 在Spring Boot主类中添加@EnableZuulProxy注解开启Zuul代理功能,并将CorsFilter注入到Spring容器中。 ```java import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.netflix.zuul.EnableZuulProxy; import org.springframework.context.annotation.Bean; @SpringBootApplication @EnableZuulProxy public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } @Bean public CorsFilter corsFilter() { return new CorsFilter(); } } ``` 通过上述配置,Zuul将会添加相应的CORS响应头,从而允许跨域请求。你可以根据实际需求修改CorsFilter中的相关配置,例如允许的请求头和请求方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值