跨域产生的原因:浏览器受到同源策略的限制,在不同域名、不同端口、不同协议等情况下不允许资源共享。
解决跨域的方法:
(1)jsonp
通常为了减轻web服务器的负载,我们把js、css,img等静态资源分离到另一台独立域名的服务器上,在html页面中再通过相应的标签从不同域名下加载静态资源,而被浏览器允许,基于此原理,我们可以通过动态创建script,再请求一个带参网址实现跨域通信。
缺点只适用于get请求方式,且只支持跨域HTTP请求,请求上存在一定的局限性,但却是最早的解决跨域问题的方法。jquery中就用此方法解决了跨域问题:
$("#demo").click(function(){
$.ajax({
url : 'http://www.demo.cn/Test/crossDomain',
data : {},
type : 'get',
dataType : 'jsonp',
success : function (res) {
conosle.log(res);
}
});
});
(2)CORS请求,只需要浏览器和服务器的支持,目前几乎所有浏览器都支持该功能。
整个CORS通信中,都是浏览器自动完成,对于开发者来说cors通信与同源的ajax没有差别。浏览器一旦发现ajax请求跨域,就会自动添加一些附加请求头,有时还会预请求一次,在预检通过后再发送请求座位数据传输。此方法需要后端修改响应头:
header(Access-control-Allow-Origin: * ');
//*代表允许访问的来源(所有),但是你在请求头携带cookie等东西时,必须要指明,也就是设置跨域白名单。
header('Access-control-Allow-Method: POST,GET'); //允许访问的方式
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。
原生ajax:
// 前端设置是否带cookie
xhr.withCredentials = true;
jquery ajax:
$.ajax({
...
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
...
});
(3)设置代理。可以简单理解为客户端发送请求时,不直接到服务器,而是先到代理的中间层;同理,当服务器返回数据时,先是到代理的中间层。
以webpack开发配置API代理解决跨域为例:
①需要使用本地开发插件:webpack-dev-server。
②配置http-proxy ,在webpack的配置文件(webpack.config.js)中进行配置
module.exports = {
...
// webpack-dev-server的配置
devServer: {
proxy: {
// 当请求是以/api开头的接口,则帮代理访问到http://localhost
'/api/*': {
target: 'http://localhost', //要代理的域名,必须要加上http
//开启代理:在本地会创建一个虚拟服务端,然后发送请求的数据,并同时接收请求的数据,
这样客户端端和服务端进行数据的交互就不会有跨域问题
changeOrigin: true,
pathRewrite:{
'^/api':'/' // 替换target地址,也就是说以后请求http://localhost/demo1地址时,
axios请求地址直接写成/api/demo1
}
}
},
...
};
在dev环境下,因为配置了proxyTable可以实现跨域。但是在生产环境中,api前缀被直接写死,导致报错。可通过判断生产环境还是开发环境来动态设置,如果是生产环境就baseUrl='',开发环境baseUrl='/api'。
axios.defaults.baseURL = (process.env.NODE_ENV===‘development’)?'/api':''