2021-03-14
阅读:28
在日常开发中,前后端数据联调过程中,跨域是我们绕不过去的一个问题,面试的时候,也经常会问到,但是,解决跨域问题大部分都是在后端/服务端去解决的,虽然感觉面试的时候问前端跨域的解决方案有点耍流氓,这里,还是整理下常见的跨域解决方案
出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。同源策略会阻止一个域的javascript脚本和另外一个域的内容进行交互。所谓同源(即指在同一个域)就是两个页面具有相同的协议(protocol),主机(host)和端口号(port)
在前后端分离项目之前,我们用的最多的是 JSONP
原理:
在开发过程中,我们可以发现,script 标签的src img标签的src link标签的src都不会受同源策略的影响,jsonp就是利用script 的scr不受同源策略影响的前提下产生的
在按钮点击(或者其他触发ajax调用)时,手动创建一个script src指向后端接口地址,同时,在地址后加上 callback函数方法名,后端生成对应的js函数调用同时把参数传递到这个callback函数里,我们只要在页面上定义好这个callback方法的处理逻辑即可 例如
$(".btn").on("click",function(){
var ele = document.createElement('script');
ele.src = 'http://api.xxx.com/getList?page=1&size=10&callback=getList';
$("body").append(ele);
})
//callback函数
function getList(arr){
//处理逻辑
}
从处理方法我们可以看出,jsonp最明显的缺点就是 只支持get请求
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
例如:在php中设置CORS
header("Content-type: application/json");
//跨域
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Origin: 跨域URL");
//CORS
header("Access-Control-Request-Methods:GET, POST, PUT, DELETE, OPTIONS");
header('Access-Control-Allow-Headers:x-requested-with,content-type,test-token,test-sessid');
前端就正常使用ajax发送请求即可
在前后端分离的项目中,例如vue-cli创建的项目,开发过程中,我们会配置代理去解决开发环境的跨域问题
vue-cli项目 vue.config.js中配置开发环境代理
module.exports = {
//公共文件路径
publicPath: '/',
//静态资源(js、css、img、fonts)目录
assetsDir: 'static',
//代码检测
lintOnSave: false,
//sourceMap
productionSourceMap: false,
//代理
devServer:{
proxy:{
'/api':{
target: "https://api.xxx.com",
pathRewrite: {
'^/api': ''
}
}
}
},
//css处理
css: {
extract: process.env.NODE_ENV === "development" ? false : true
}
}
如上,我们配置了以 api 开头的请求都会使用代理转发到 https://api.xxx.com 这个接口域名下 代码里我们可以直接以api开头去发送请求
//以api开头的请求会代理到 https://api.xxx.com 这个域名下,实际请求路径为 https://api.xxx.com/getUser
axios.get('/api/getUser').then((res)=>{
})
在项目开发完成后,我们在生产环境部署的时候,可以使用 nginx 设置反向代理 nginx简单配置 在 server下增加如下配置
#接口代理
location ~ /api/ {
rewrite ^.+api/?(.*)$ /$1 break;
proxy_pass https://api.xxx.com;
}