在前后端分离项目中,跨域是一定会出现的问题,本文主要介绍跨域问题的解决思路,以及在vue项目中如何使用代理的方式在前端解决跨域问题,同时提供一个后段解决的方案。
1、产生原因
跨域问题产生的原因是浏览器的同源策略。浏览器同源策略是浏览器中的一种安全机制,用于防止一个域下的文档或脚本访问另一个域下的文档或脚本。同源指的是两个URL的协议、主机名和端口号都相同,只有这些都相同的情况下,两个文档之间才满足同源条件。
也就是指,当浏览器地址栏的地址(页面访问地址)和接口访问地址不一样时就会出现跨域问题,浏览器会拦截服务器返回的数据,并报CROS错误。
例如浏览器地址是:localhost:8080/xxx
,访问的接口地址是:http://23.43.222.12:8080/xxx
,这时候就会出现跨域问题。所以在前后端分离的项目,跨域问题是必然出现的。
注意:
- 如果主机一样,但是端口不一样也会产生跨域问题,例如浏览器地址栏:
localhost:8080/xxx
,接口地址:http://localhost:8081/xxx
,也是跨域。
2、解决思路
从原因中可以看到,问题产生主要是浏览器的锅,两个服务(后段)之间进行接口调用是不会产生跨域的,因此我们可以使用一个代理,通过代理服务器去调用server,代理服务器返回数据到浏览器,如下图所示
此处的代理,本质就是一个后端服务,通过代理(后端服务)去调用server,拿到数据后在返回给浏览器,同时非常重要的一点,代理服务的访问地址必须和浏览器地址栏中的端口地址一样(localhost:8080),在Vue中提供了这个功能,只需要进行简单的配置即可实现。
3、问题解决
3.1 前端解决
1、找到vue项目中的vue.config.js
,在其中的module.exports
中添加如下代码,来配置一个代理proxy,作用见注释。
devServer: {
proxy: {
//配置跨域
"/api": { //url识别符
target: "http://23.43.222.12:8080/", // server地址
changOrigin: true, //允许跨域
pathRewrite: {
/* 重写路径,当我们在浏览器中看到请求的地址为:http://localhost:8080/api/core/getData/userInfo 时
实际上访问的地址是:http://23.43.222.12:8080/core/getData/userInfo,因为重写了 /api
*/
"^/api": "",
},
},
},
},
2、在使用axios等进行接口调用时,不是调用http://23.43.222.12:8080/core/getData/userInfo
,而是调用http://localhost:8080/api/core/getData/userInfo
3.2 后段解决
前后端分离,java的话一般使用springboot项目,以springboot为例,添加如下配置:
@Configuration
public class GlobalCorsConfig {
@Bean
public CorsFilter corsFilter() {
//1.添加CORS配置信息
CorsConfiguration config = new CorsConfiguration();
//放行哪些原始域
config.addAllowedOrigin("*");
//是否发送Cookie信息
config.setAllowCredentials(true);
//放行哪些原始域(请求方式)
config.addAllowedMethod("*");
//放行哪些原始域(头部信息)
config.addAllowedHeader("*");
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
// config.addExposedHeader("*");
config.addExposedHeader("Content-Type");
config.addExposedHeader( "X-Requested-With");
config.addExposedHeader("accept");
config.addExposedHeader("Origin");
config.addExposedHeader( "Access-Control-Request-Method");
config.addExposedHeader("Access-Control-Request-Headers");
//2.添加映射路径
UrlBasedCorsConfigurationSource configSource = new UrlBasedCorsConfigurationSource();
configSource.registerCorsConfiguration("/**", config);
//3.返回新的CorsFilter.
return new CorsFilter(configSource);
}
}