优雅的解决跨域问题
想要解决跨域问题,我们首先要清楚什么是跨域
每当我们请求后端识别后打开控制台出现了No ‘Access-Control-Allow-Origin’ header is present on the requesting resource
跨域是只在网页中,当一个网页试图去访问不同域名下的资源时(比如发送ajax请求,使用iframe加载其他网页等)会受到同源策略的限制,从而导致无法正常获取数据的情况
同源策略是指:协议、域名、端口都相同的两个网址
为什么浏览器需要跨域
浏览器之所以限制跨域,是因为处于安全顾虑。
如果不限制跨域访问,那么攻击者就可以伪造请求,访问用户在其他网站上的敏感信息或只执行恶意操作
第一种解决方法:
JSONP是一种利用script标签的GET请求实现跨域的技术
简答的案例:
假设我们有一个网站A,想要获取另一个网站B的数据,但是B和A不在同一个域,因此不能直接访问。
在B网站
的服务器端,提供了一个名为getData的接口
,可以返回一些数据。为了让A网站
可以获取这些数据,B网站在返回数据时将其封装在一个名为callback的回调函数
中,并将回调函数的参数作为需要的数据传给A网的。A网站使用JSONP来获取B网站的数据,并指定一个名为handleResponse的回调函数。
B网站后端返回数据的代码如下:
var data = {
"name": "Alice",
"age": 18
};
var callback = req.query.callback; // 获取回调函数的名称
res.send(callback + '(' + JSON.stringify(data) + ')'); // 将数据封装在回调函数中返回
A网站前端请求代码如下:
function handleResponse(data) {
console.log(data);
}
var script = document.createElement('script');
script.src = 'http://www.domain2.com/getData?callback=handleResponse';
document.head.appendChild(script);
JSONP的优点是可以实现跨域请求,而且兼容性好,几乎所有浏览器都支持。但是它也有一些弊端:
1.只支持GET请求,因为jsonp是通过动态创建script标签来实现跨预期扭曲的,而script标签只支持GET请求
2.数据格式限制,JSONP只能返回JSON格式的数据,无法返回XML格式的数据
代理的方式
就是自己搭一个本地服务器,通过访问服务器与服务器的关系,跨过浏览器这的同源策略
。
Webpack devserver
如果是大型配置,并且配置了webpack的话
1.如果在Webpack的配置文件中添加devServer.proxy属性来实现跨域代理
// webpack.config.js
module.exports = {
// ...
devServer: {
proxy: {
'/api': {
target: 'http://www.domain2.com', //需要跨域的url
changeOrigin: true,
pathRewrite: {
'^/api': ''
}
}
}
}
}
注意,如果在代理配置中设置了changeOrigin为true,则在代理请求时会自动将请求头中的Host字段设置为代理目标的域名,这样就可以绕过浏览器的同源策略,实现跨域请求。
axios.get('/api/data')
.then(response => {
console.log(response.data)
})
.catch(error => {
console.log(error)
})
CORS
我们不需要为每个WebAPI做额外的处理,而是需要在后端程序启动时,增加一些处理工作。主流的后端服务都有处理CORS的类库,这里就不再做展开介绍了。
这个方案的核心原理,是在发起正式的请求前,先发送一个OPTIONS谓词的HTTP请求,询问发起请求的页面是否有调用该域服务的权限;如果后端说OK,浏览器就继续请求,否则提示错误。
使用这种方案的开发工作量小,如果直接使用成熟类库的话,开发和测试的工作量甚至可以忽略不计。不过,因为每个跨域的请求都会触发一次往外的OPTIONS请求,对服务器会造成额外的开销和压力。