目录
1.跨域概念
2.解决方法
2.1 配置网络请求代理
2.2 使用@CrossOrigin 注解
2.3 通过配置文件实现跨域
2.4 添加 CorsWebFilter 来解决跨域问题
1.跨域概念
- 跨域问题是由于浏览器实施了同源策略,该策略要求请求的域名、协议和端口必须与提供资源的服务相同。如果不相同,则需要服务器显式地允许这种跨域请求。
- 一般在springboot+vue前后端分离项目中,前端应用(Vue.js)通常运行在一个不同的域名或端口上,而后端服务(Spring Boot)则运行在另一个,则会产生跨域问题。
2.解决方法
2.1 配置网络请求代理
在vue项目的vue.config.js 中配置网络请求代理,代码如下:
devServer: {
proxy: {
'/api': { // 匹配所有以 /api 开头的请求路径
target: 'url',//指定代理的目标服务器地址,即后端服务的实际地址。
pathRewrite:{
'^/api':'' //将请求地址中的/api替换为空字符
},
changeOrigin: true
}
}
}
网络请求代理原理:
- 一个项目可以分为三个部分,浏览器,前端服务器,后端服务器。浏览器首先会向前端服务器发出请求,拿到页面,然后再向后端发出请求,拿到数据填充到页面中。但是由于浏览器的同源策略,当浏览器向再向后端发出请求时,就会报错。
- 网络请求代理的原理是,在前端服务器中设置一个网络代理,如下图,当浏览器发出以 api 开头的请求时,可以认为是请求后端的数据,否则是请求页面。 当请求后端的数据时,就在前端服务中设置一个访问后端的目标url,这个url访问到数据后,响应给浏览器,这样浏览器就只需要和前端服务器进行交互,间接避免了浏览器的同源策略。
2.2 使用@CrossOrigin 注解
这个主要是针对后端而言,使用 @CrossOrigin 注解可以实现跨域,此注解既可以修饰类,也可以修饰方法。当修饰类时,表示此类中的所有接口都可以跨域;当修饰方法时,表示此方法可以跨域,它的实现如下:
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.HashMap;
@RestController
@CrossOrigin(origins = "*")//该类的所有单元方法均可实现跨域访问
public class TestController {
@RequestMapping("/test")
public HashMap<String, Object> test() {
return new HashMap<String, Object>() {{
put("state", 200);
put("data", "success");
put("msg", "");
}};
}
}
注:使用此方式只能实现局部跨域,当一个项目中存在多个类的话,使用此方式就会比较麻烦(需要给所有类上都添加此注解)。
2.3 通过配置文件实现跨域
通过设置配置文件的方式就可以实现全局跨域了,它的实现步骤如下:
- 创建一个新配置文件。
- 添加 @Configuration 注解,实现 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.addMapping("/**") // 所有接口
.allowCredentials(true) // 是否发送 Cookie
.allowedOriginPatterns("*") // 支持域
.allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE"}) // 支持方法
.allowedHeaders("*")
.exposedHeaders("*");
}
}
2.4 添加 CorsWebFilter 来解决跨域问题
在 Spring-Framework 从 5.3 版本之前,使用以下代码可以让 Spring Cloud Gateway 网关允许跨域:
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
// 这里仅为了说明问题,配置为放行所有域名,生产环境请对此进行修改
config.addAllowedOrigin("*");
// 放行的请求头
config.addAllowedHeader("*");
// 放行的请求类型,有 GET, POST, PUT, DELETE, OPTIONS
config.addAllowedMethod("*");
// 暴露头部信息
config.addExposedHeader("*");
// 是否允许发送 Cookie
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
而 Spring-Framework 5.3 版本之后,关于 CORS 跨域配置类 CorsConfiguration 中将 addAllowedOrigin 方法名修改为 addAllowedOriginPattern,因此配置了变成了以下这样:
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsWebFilter corsWebFilter() {
CorsConfiguration config = new CorsConfiguration();
// 这里仅为了说明问题,配置为放行所有域名,生产环境请对此进行修改
config.addAllowedOriginPattern("*");
// 放行的请求头
config.addAllowedHeader("*");
// 放行的请求类型,有 GET, POST, PUT, DELETE, OPTIONS
config.addAllowedMethod("*");
// 暴露头部信息
config.addExposedHeader("*");
// 是否允许发送 Cookie
config.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", config);
return new CorsWebFilter(source);
}
}
注:部分知识点总结来源于:https://zhuanlan.zhihu.com/p/679740296 ,想进一步了解的,可以去看。