问题概述
关于这个问题,博主是在跨服务调用的时候遇到的,相同的域名,不同的端口,
不同服务间调用,提示跨域:
“ Access to XMLHttpRequest at 'http://***.***.***:****/api/sys/login' from origin 'http://***.***.***:****' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. ”
如下图:
预检请求跨域:
解决办法
关于这个问题,其实很简单,作为一个码农,需要知其然,还需要知其所以然!
(如果只想知其然,解决问题,请划到最下面代码处)
一、什么是跨域?
跨域指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
二、什么是同源策略?
同源策略是指协议,域名,端口都要相同,其中有一个不同都会产生跨域。
三、跨源资源共享(CORS)?
跨源资源共享(CORS,或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其他源(域、协议或端口),使得浏览器允许这些源访问加载自己的资源。跨源资源共享还通过一种机制来检查服务器是否会允许要发送的真实请求,该机制通过浏览器发起一个到服务器托管的跨源资源的“预检”请求。在预检中,浏览器发送的头中标示有 HTTP 方法和真实请求中会用到的头。
跨源 HTTP 请求的一个例子:运行在 https://domain-a.com 的 JavaScript 代码使用 XMLHttpRequest 来发起一个到 https://domain-b.com/data.json 的请求。
出于安全性,浏览器限制脚本内发起的跨源 HTTP 请求。例如,XMLHttpRequest 和 Fetch API 遵循同源策略。这意味着使用这些 API 的 Web 应用程序只能从加载应用程序的同一个域请求 HTTP 资源,除非响应报文包含了正确 CORS 响应头。
CORS 机制允许 Web 应用服务器进行跨源访问控制,从而使跨源数据传输得以安全进行。现代浏览器支持在 API 容器中(例如 XMLHttpRequest 或 Fetch)使用 CORS,以降低跨源 HTTP 请求所带来的风险。
四、CORS 概述?
跨源资源共享标准新增了一组 HTTP 标头字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。另外,规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨源请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(例如 Cookie 和 HTTP 认证相关数据)。
CORS 请求失败会产生错误,但是为了安全,在 JavaScript 代码层面无法获知到底具体是哪里出了问题。你只能查看浏览器的控制台以得知具体是哪里出现了错误。
五、解决办法一:WebMvcConfigurer(Spring Boot Interface)
通过实现Spring Boot的WebMvcConfigurer接口的跨域方法addCorsMappings,配置跨域标头:
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
// 对所有路径应用 CORS 配置
.addMapping("/**")
// 允许所有域名进行跨域调用
.allowedOriginPatterns("*")
// 允许跨域发送cookie
.allowCredentials(true)
// 放行全部原始头信息
.allowedHeaders("*")
// 允许所有请求方法跨域调用
.allowedMethods("OPTIONS", "GET", "POST", "PUT", "DELETE")
// 指定预检请求结果缓存时间
.maxAge(3600);
}
}
六、解决办法二:CorsWebFilter (Spring Framework API)
CorsWebFilter 是 Spring Framework 中的一个过滤器,用于处理跨源资源共享(CORS)的请求。CORS 是一种 W3C 规范,它定义了一种浏览器和服务器交互的方式来确定是否允许跨源请求。
在 Spring WebFlux(响应式编程模型)或 Spring MVC(传统的基于 Servlet 的模型)应用中,可以使用 CorsWebFilter 来配置 CORS 策略。这个过滤器允许自定义哪些源(域、协议和端口)有权访问指定的应用资源,哪些 HTTP 方法被允许,哪些头信息可以被包含,以及预检请求的存活时间等。
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 MyCorsConfiguration {
@Bean
public CorsWebFilter corsWebFilter() {
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
// 跨域配置
// 放行全部原始头信息
corsConfiguration.addAllowedHeader("*");
// 允许所有请求方法跨域调用
corsConfiguration.addAllowedMethod("*");
// 允许所有域名进行跨域调用
corsConfiguration.addAllowedOriginPattern("*");
// 允许跨域发送cookie
corsConfiguration.setAllowCredentials(true);
// 对所有路径应用 CORS 配置
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
return new CorsWebFilter(urlBasedCorsConfigurationSource);
}
}
七、验证CORS
预检成功!真实请求成功调用!
参考文献:
【UrlBasedCorsConfigurationSource API】
好了,关于 CORS policy: ***No ‘Access-Control-Allow-Origin‘ header is present on the requested resource 跨域的解决办法 就写到这儿了,如果还有什么疑问或遇到什么问题欢迎扫码提问,也可以给我留言哦,我会一一详细的解答的。
歇后语:“ 共同学习,共同进步 ”,也希望大家多多关注CSND的IT社区。
作 者: | 华 仔 |
联系作者: | who.seek.me@java98k.vip |
来 源: | 优快云 (Chinese Software Developer Network) |
原 文: | https://blog.youkuaiyun.com/Hello_World_QWP/article/details/140949607 |
版权声明: | 本文为博主原创文章,请在转载时务必注明博文出处! |