目录
1、跨域问题说明
2、跨域解决方案
2.1、局部跨域解决方案
2.1.1、@CrossOrigin注解跨域
2.1.2、手动设置响应头
2.2、全局跨域解决方案
2.2.1、实现WebMvcConfigurer接口设置跨域
2.2.2、定义CorsFilter Bean实现跨域
2.2.3、重写ResponseBodyAdvice接口中的beforeBodyWrite方法实现跨域
2.2.4、nginx配置跨域(nginx.conf)
3、跨域常见异常问题
3.1、No 'Access-Control-Allow-Origin' header is present on the requested resource
3.2、header contains multiple values 'XXX, *', but only one is allowed
1、跨域问题说明
- 同源:两个页面具有相同的协议、域名和端口。
- 跨域:当一个请求url的协议、域名或端口之中任意一个与当前页面url不同。
- 跨域产生原因:浏览器设置了同源策略,当页面执行脚本的时候,浏览器会检查访问的资源是否同源,如果不是,就会报错。
举例说明:
2、跨域解决方案
通过在响应头中设置Access-Control-Allow-Origin,表示允许跨域访问的原始域名,告诉浏览器这是一个安全请求,即可解决跨域问题。
当设置Access-Control-Allow-Origin = * 时,表示允许所有站点跨域访问。
2.1、局部跨域解决方案
2.1.1、@CrossOrigin注解跨域
该注解可以修饰类和方法。设置简单,但需要为所有类或方法都加上注解。
@RestController
@CrossOrigin(origins = "*")
public class TestController {
@RequestMapping("/test")
public String test() {
return "测试@CrossOrigin解决跨域问题";
}
}
2.1.2、手动设置响应头
方法级别的跨域。
@RestController
public class TestController {
@RequestMapping("/test")
public String test(HttpServletResponse response) {
response.addHeader("Access-Control-Allow-Origin", "*");
response.addHeader("Access-Control-Max-Age", "10");
response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
response.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT");
response.setHeader("Access-Control-Allow-Credentials", "true");
return "测试手动设置响应头解决跨域问题";
}
}
2.2、全局跨域解决方案
2.2.1、实现WebMvcConfigurer接口设置跨域
通过实现WebMvcConfigurer接口里的addCorsMappings方法设置跨域。
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") // 匹配所有接口
.allowCredentials(true) // 是否发送 Cookie
.allowedOriginPatterns("*") // 支持域
.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"}) // 支持方法
.allowedHeaders("*")
.exposedHeaders("*");
}
}
2.2.2、定义CorsFilter Bean实现跨域
@Configuration
public class MyCorsFilter {
@Bean
public CorsFilter corsFilter() {
// 1.创建 CORS 配置对象
CorsConfiguration config = new CorsConfiguration();
config.addAllowedOriginPattern("*"); // 支持域
config.setAllowCredentials(true); // 是否发送 Cookie
config.addAllowedMethod("*"); // 支持请求方式
config.addAllowedHeader("*"); // 允许的原始请求头部信息
config.addExposedHeader("*"); // 暴露的头部信息
// 2.添加地址映射
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**", config);
// 3.返回 CorsFilter 对象
return new CorsFilter(corsConfigurationSource);
}
}
2.2.3、重写ResponseBodyAdvice接口中的beforeBodyWrite方法实现跨域
@ControllerAdvice
public class ResponseAdvice implements ResponseBodyAdvice {
/**
* 是否重写响应内容
* 返回 true 表示重写
*/
@Override
public boolean supports(MethodParameter returnType, Class converterType) {
return true;
}
/**
* 方法返回之前调用此方法
*/
@Override
public Object beforeBodyWrite(Object body, MethodParameter returnType, MediaType selectedContentType,
Class selectedConverterType, ServerHttpRequest request,
ServerHttpResponse response) {
// 设置跨域
response.getHeaders().set("Access-Control-Allow-Origin", "*");
return body;
}
}
2.2.4、nginx配置跨域(nginx.conf)
nginx在获取下游响应后,在响应头中加上如下配置:
add_header Access-Control-Allow-Origin * always;
add_header Access-Control-Allow-Credentials 'true' always;
add_header Access-Control-Allow-Headers * always;
add_header Access-Control-Allow-Methods 'PUT, GET, POST, DELETE, OPTIONS' always;
if ($request_method = 'OPTIONS') {
return 204;
}
3、跨域常见异常问题
3.1、No 'Access-Control-Allow-Origin' header is present on the requested resource
XXXX from origin XXXX has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource
- 原因:响应结果未增加Access-Control-Allow-Origin头。
- 解决方案:后端解决方案可参照《2、跨域解决方案》。
3.2、header contains multiple values 'XXX, *', but only one is allowed
The 'Access-Control-Allow-Origin' header contains multiple values 'http://localhost:8080, *', but only one is allowed. Origin 'http://localhost:8080' is therefore not allowed access.
- 原因:跨域重复设置,比如在nginx设置了跨域,又在业务服务中设置了跨域,最后的响应中就会有多个Access-Control-Allow-Origin值。
- 解决方案:请求全流程保证只进行一次跨域设置即可。
以上内容为个人学习理解,如有问题,欢迎在评论区指出。
部分内容截取自网络,如有侵权,联系作者删除。