一、跨域请求
在请求时,如果出现了以下情况中的任意一种,那么它就是跨域请求:
协议不同,如 http 和 https;
域名不同;
端口不同;
二、跨域报错示例
三、解决方法
通常跨域问题使用以下6个方法解决
-
使用 @CrossOrigin 注解实现跨域;
-
通过配置文件实现跨域;
-
通过 CorsFilter 对象实现跨域;
-
通过 Response 对象实现跨域;
-
通过实现 ResponseBodyAdvice 实现跨域;
-
使用过滤器来实现跨域;
1 、通过@CrossOrigin注解跨域
@CrossOrigin注解可以修饰类和方法。当修饰类时,表示此类中的所有接口都可以跨域;当修饰方法时,表示此方法可以跨域,
@RestController
@RequestMapping("user")
@CrossOrigin(origins = "*")
public class UserController {
@PostMapping(value = "login")
public String login() {
return "姓名:张三;性别:男";
}
}
优点:实现跨域非常简单
缺点:只能实现局部跨域,当一个项目中存在多个类时,需要给所有类上都添加此注解,比较麻烦
2 、通过配置文件跨域
通过配置文件的方式可实现全局跨域
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
//支持所有接口
registry.addMapping("/**")
//是否发送Cookie
.allowCredentials(true)
//支持域
.allowedOriginPatterns("*")
.allowedMethods("GET", "POST", "PUT", "DELETE")
.allowedHeaders("*")
.exposedHeaders("*");
}
}
3、 通过CorsFilter跨域
可实现全局跨域
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
@Configuration
public class GlobalCorsFilter {
@Bean
public CorsFilter corsFilter() {
CorsConfiguration config = new CorsConfiguration();
//支持域
config.addAllowedOriginPattern("*");
//是否发送Cookie
config.setAllowCredentials(true);
//支持请求方式
config.addAllowedMethod("*");
//允许的原始请求头部信息
config.addAllowedHeader("*");
//暴露的头部信息
config.addExposedHeader("*");
//添加地址映射
UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
corsConfigurationSource.registerCorsConfiguration("/**", config);
return new CorsFilter(corsConfigurationSource);
}
}
4、 通过Response跨域
解决跨域问题最原始的方式,支持任意版本的Spring Boot。但也是局部跨域,仅支持方法级别的跨域
@RestController
@RequestMapping("user")
public class UserController {
@PostMapping(value = "login")
public String login(HttpServletResponse response) {
response.setHeader("Access-Control-Allow-Origin", "*");
return "姓名:张三;性别:男";
}
}
5 、通过ResponseBodyAdvice跨域
通过重写ResponseBodyAdvice接口中的beforeBodyWrite(返回之前重写)方法,可以对所有的接口设置跨域
为全局跨域,对整个项目中的所有接口有效
@ControllerAdvice
public class CorsResponseBodyAdvice implements ResponseBodyAdvice {
/**
* 内容是否需要重写
* 可以选择部分控制器和方法进行重写
* <p>
* 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;
}
}
6、 使用过滤器跨域
实现方式同3.5,不再赘述
四、原理
跨域问题本质上是浏览器的行为,它的初衷是为了保证用户的访问安全,防止被恶意网站窃取数据。因此解决跨域问题就只是需要告诉浏览器这是一个安全的请求就可以了,告诉浏览器“我是自己人”。
那怎么告诉浏览器这是一个安全的请求呢?只需要在返回头中设置“Access-Control-Allow-Origin”参数即可。此参数就是用来表示允许跨域访问的原始域名的,当设置为“*”时,表示允许所有站点跨域访问
未设置跨域时:
设置跨域后: