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
  * <p>
  * 反之,就是非简单跨域,此跨域有一个预检机制,说直白点,就是会发两次请求,一次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");
	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);
			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: "http://domain.com"
						allowedMethods:
							- GET
							- POST
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Cloud Gateway是Spring Cloud生态圈中的一个API网关,它提供了一种构建微服务架构的解决方案跨域是Web开发中常见的问题,特别是在微服务架构中,不同服务之间需要进行跨域访问。本篇文章将介绍使用Spring Cloud Gateway实现跨域的方法。 首先,需要在Spring Cloud Gateway中添加Corsconfiguration Bean,代码如下: @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("*")); configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE")); configuration.setAllowedHeaders(Arrays.asList("Content-Type", "Authorization")); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; } 然后,在application.yml文件中添加跨域配置,代码如下: spring: cloud: gateway: globalcors: corsConfigurations: '[/**]': allowedOrigins: "*" allowedMethods: - GET - POST - PUT - DELETE allowedHeaders: - "Content-Type" - "Authorization" allowCredentials: true maxAge: 3600 这里设置了允许的来源,方法和头部,还指定了是否允许发送cookie信息,以及最大响应时间。此外,您也可以通过使用代码配置来自定义跨域规则,具体请参考Spring Cloud Gateway官方文档。 最后,在需要进行跨域访问的路由前添加跨域过滤器,代码如下: @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("path_route", r -> r.path("/hello") .filters(f -> f.addRequestHeader("Hello", "World") .addFilter(new CrossOriginFilter())) .uri("http://localhost:8081")) .build(); } 在这个例子中,我们将拦截/hello路由,并添加一个跨域过滤器。 总结来说,使用Spring Cloud Gateway实现跨域需要以下步骤:添加Corsconfiguration Bean,配置application.yml文件,添加跨域过滤器。这样,在微服务架构中实现跨域问题就变得容易了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值