之前做了一个小项目,采用前后端分离的架构(Vue+pringBoot),遇到了跨域的问题,简单记录一下~~
目录
后端采用cors实现跨域
前端使用http-proxy-middleware 代理来实现跨域
Vue官方推荐使用axios,是轻量版的ajax,来实现前后端交互。
当前端调用后端的一个getPersionInformation api时,没有成功,打开chrome控制台时,报以下错误:
这是很明显的跨域问题:P
上面特殊的是:
虽然Status Code是200
但Request Method: OPTIONS
这里的OPTIONS是啥东西?
axios官方文档的解释大概的意思是:浏览器自动在跨域的 GET 请求发送之前发送一个 OPTIONS 请求,以判断服务端是否允许这一域访问。
因此服务器端(即后端)除了要有跨域头之外还要允许的 header 头。
后端采用cors实现跨域
那后端怎么实现呢?W3C提供了跨域请求的标准方案(Cross-Origin Resource Sharing(跨域资源共享))。通过它,后端开发者就可以决定资源是否能被跨域访问。只要服务端实现了CORS接口,就可以跨源通信。
由于后端采用了springboot,springmvc早已经支持了对cors的支持,springboot完美地继承了对其支持。
@Configuration
public class MyWebAppConfigurer extends WebMvcConfigurerAdapter{
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**");
}
只要进行如上配置,就能全局配置了。注意“/**”代表允许所有路径。也可以对registry进行自定义的属性配置~~
当然springboot还提供了一个很简单的注解就能实现跨域的功能@CrossOrigin
@CrossOrigin(origins = "http://192.xx.xx.xx:8080", maxAge = 3600)
@RestController
public class UserController{
@GetMapping("/getPersonalInformation")
public String getUser() {
//具体的操作--
}
}
如上使用这个注解,其只对指定的类中的所有方法起效。如果@CrossOrigin加在具体方法的上面,那就只对该方法起效。这样方便细粒化控制。
按理说这样就可以了,事实上当初的确可以了,但最近一次demo这样做发现不行。有点玄学的意味~~
前端使用http-proxy-middleware 代理来实现跨域
既然这样有时候不太行,那就换一条思路,对前端使用http-proxy-middleware 代理
由于前端是Vue,那我们自己来修改配置,来实现http-proxy-middleware的简单使用
1.打开config/index.js,在proxyTable中添写如下代码:
proxyTable: {
'/api': {
target:'http://112.74.xx.xxx:8080', // 你接口的域名
//secure: false, // 如果是https接口,需要配置这个参数
changeOrigin:true, // 如果接口跨域,需要进行这个参数配置
pathRewrite: {
'^/api':'http://112.74.xx.xxx:8080'
}
}
},
注意:changeOrigin
参数,接收一个布尔值,如果设置为true
,那么本地会虚拟一个服务端接收你的请求并代你发送该请求,这样就不会有跨域问题了,所以这只适用于开发环境。
2.使用axios发送get请求时直接使用“/api”:
getPersonalInformation:function () {
var token='Bearer '+sessionStorage.getItem("Token");
let config = {
headers: {
'Authorization':token
}
};//将token放入header中,如果没有请忽略
console.log(token);
var url = "/api/getPersonalInformation";
console.log(url);
this.$axios.get(url,config).then(res=> {
console.log(res);
}) .catch( res => {
console.log(res);
})}
其原理:
前端访问http://112.74.xx.xxxx:8080:/getPersonalInformation 就当于访问了:localhost:8080/api/getPersonalInformation(其中localhost:8080是虚拟服务端的IP和端口)。然后在index.js中的proxyTable中拦截了/api,并把/api及其前面的所有替换成了target中的内容,因此实际访问Url是http://api/getPersonalInformation
3.如果是生产环境的话,那就一般可以用nginx来实现跨域。
修改nginx配置文件
location /api {
add_header 'Access-Control-Allow-Origin' '*';
proxy_pass http://112.74.xx.xxxx:8080;
}
即可。
这样项目前后端交互就能正常工作了。
ps:然后我把后端cors配置全部注释掉,发现又不行了。最近这个demo很玄学,必须前后端都进行跨域处理,才能正常交互~~ :P。