摘要:
本文整理了在开发工作中遇到的几种跨域问题浏览器控制台产生的报错信息,针对这几种报错信息进行分析,并尝试解决。旨在通过对这些问题的分析,反映出结合浏览器报错信息,对跨域问题的调试方法。
跨域问题基础理论
- 同源策略是浏览器安全的基石,为了保证用户信息的安全,防止恶意的网站窃取数据。
- 同源是指:
- 协议相同
- 域名(主机名)相同
- 端口相同
那么,一个源访问另一个源的资源时即为「跨源」,最常见的跨源场景是域名不同,即常说的“跨域”。
在跨域的情形下,
- 无法读取非同源网页的 Cookie、LocalStorage 和 IndexedDB
- 无法接触非同源网页的 DOM
- 无法向非同源地址发送 AJAX 请求(可以发送,但浏览器会拒绝接受响应
报错信息总览
跨域产生的问题存在的错误提示存在以下几种情况(但不限于以下情况)
案例一
- 没有进行任何跨域设置,跨域请求发起后的报错如下
Access to XMLHttpRequest at ‘http://localhost:10010/api/sys/login’ from origin ‘http://localhost:8001’ 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.
分析:重点信息在于最后一句话:请求的参数中没有设置 Access-Control-Allow-Origin
处理办法:进行跨域请求的处理 配置。
案例二
- 多处进行了跨域处理 ,其中涉及重复操作,下面以 重复设置 Origin为例。即在两个地方都设置允许跨源的操作。
Response to preflight request doesn’t pass access control check: The value of the ‘Access-Control-Allow-Origin’ header in the response must not be the wildcard ‘*’ when the request’s credentials mode is ‘include’. The credentials mode of requests initiated by the XMLHttpRequest is controlled by the withCredentials attribute.
分析:关键信息在于 通过 withCredentials 属性控制 credentials mode ,而 该模式与当前设置 Origin为* 产生冲突,因此处理办法为 对 Credentials 进行设置。
corsConfiguration.setAllowCredentials(true);
案例三
- 多处进行了跨域处理 ,其中涉及重复操作,下面以 重复设置 Origin为例。即在两个地方都设置允许跨源的操作。
The ‘Access-Control-Allow-Origin’ header contains multiple values ‘http://localhost:8001, http://localhost:8001’, but only one is allowed.
基于gateway 的跨域设置:
如果是微服务项目,可采用gateway来处理
@Configuration
public class MallCrosConfiguration {
@Bean
public CorsWebFilter corsWebFilter(){
UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
CorsConfiguration corsConfiguration = new CorsConfiguration();
corsConfiguration.addAllowedHeader("*");
corsConfiguration.addAllowedMethod("*");
corsConfiguration.addAllowedOrigin("*");
corsConfiguration.setAllowCredentials(true);
urlBasedCorsConfigurationSource.registerCorsConfiguration("/**",corsConfiguration);
return new CorsWebFilter(urlBasedCorsConfigurationSource);
}
}
基于WebMvcConfigurer的跨域设置:
如果是springboot 单体架构项目,可采用 实现 WebMvcConfigurer 接口 来处理
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowCredentials(true)
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS")
.maxAge(3600);
}
}