首页 > 编程知识 正文

如何实现跨域访问,跨域访问问题

时间:2023-05-06 02:46:22 阅读:47015 作者:2620

Spring Cloud从构成域间访问的五个方案(https://segment fault.com/a/11900017188296 )传输并添加了自己的方案() ) ) ) ) ) )

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

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

首先介绍在SpringBoot层实现的三种方案。解决方案一:在Controller上添加@CrossOrigin注解

该方案适用于只有一个或两个rest接口需要跨域或没有网关的情况,该处理方案非常简单,适合根据原始基代码进行修改,影响相对较小。

@CrossOrigin //注释方式@ restcontrollerpublicclasshandlerscancontroller { @ cross origin (allow credentials=' true ',alllows ) RequestMethod.POST,RequestMethod.DELETE,RequestMethod.OPTIONS,request method.he eter request method.patch },定向} } 解决方案二:增加WebMvcConfigurer全局配置

如果有大量的rest接口,第一种情况显然不合适,而且工作量大,也容易出错,则全局配置必须确保SpringBoot端的所有rest接口都支持域间访问在这种情况下,必须考虑安全问题。

代码如下。

@ configurationpublicclassmyconfiguration { @ beanpublicwebmvcconfigurercorsconfigurer (} { returnnewwebmvconfigurereradapter } ) { @ overridepublicvoidaddcorsmappings (corsregistryregistry ) registry.addmapping('/** ' ).allowcredentials ) true ; } } 解决方案三:结合Filter使用

使用此方案的场景类似于第二个方案,但可以用使用过滤器的方法替代。

将CORS过滤器添加到spring boot的主类中

/** * attention:的简单跨域是GET、HEAD和POST请求,而POST请求的“Content-Type”是应用程序/x-www-form-urlerent-type 坦率地说,两次请求、一次选项请求、一次真正请求*/@ beanpubliccorsfiltercorsfilter ({ finalurlbasedcorsconfigurationsourcorsfilter ) 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代码类即可。

private static final String ALL = "*";private static final String MAX_AGE = "18000L";@Overridepublic 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);}

或者

在网关中定义“MyCorsConfiguration”类,该类用来做过滤,允许所有的请求跨域。

@Configurationpublic class MyCorsConfiguration { @Bean public CorsWebFilter corsWebFilter(){ UrlBasedCorsConfigurationSource source=new UrlBasedCorsConfigurationSource(); CorsConfiguration corsConfiguration = new CorsConfiguration(); corsConfiguration.addAllowedHeader("*"); corsConfiguration.addAllowedMethod("*"); corsConfiguration.addAllowedOrigin("*"); corsConfiguration.setAllowCredentials(true); source.registerCorsConfiguration("/**",corsConfiguration); return new CorsWebFilter(source); }}

解决方案五,修改Gateway配置文件(不好使,大概率不起效)
在仔细阅读过Gateway的文档你就会发现,原来CorsFilter早已经在Gateway里了,不需要自己写代码实现,而且更灵活,修改配置文件即可,结合配置中心使用,可以实现动态修改。
application.yml.

spring: cloud: gateway: globalcors: cors-configurations: '[/**]': # 允许携带认证信息 # 允许跨域的源(网站域名/ip),设置*为全部 # 允许跨域请求里的head字段,设置*为全部 # 允许跨域的method, 默认为GET和OPTIONS,设置*为全部 # 跨域允许的有效期 allow-credentials: true allowed-origins: - "http://localhost:13009" - "http://localhost:13010" allowed-headers: "*" allowed-methods: - OPTIONS - GET - POST max-age: 3600 # 允许response的head信息 # 默认仅允许如下6个: # Cache-Control # Content-Language # Content-Type # Expires # Last-Modified # Pragma

以上五种跨域方案。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。