一、跨域概念:
- 跨域:指的是浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对javascript施加的安全限制。
例如:a页面想获取b页面资源,如果a、b页面的协议、域名、端口、子域名不同,所进行的访问行动都是跨域的,而浏览器为了安全问题一般都限制了跨域访问,也就是不允许跨域请求资源。注意:跨域限制访问,其实是浏览器的限制。理解这一点很重要!!!
- 同源策略:是指协议,域名,端口都要相同,其中有一个不同都会产生跨域;
二、非同源限制
无法读取非同源网页的cookie、localStorage、IndexedDB
无法接触非同源网页的DOM
无法向非同源地址发送 AJAX 请求
三、解决跨域的方法:
1. JSONP
原理:有些标签 script
、img
、link
、iframe
... 这些标签不存在跨域请求的限制,就是利用这个特点解决跨域问题。JSONP 是服务器与客户端跨源通信的常用方法。
优点:简单适用,兼容性好(可以兼容低版本IE),
缺点:只支持 get 请求,不支持 post 请求,导致数据不安全
核心思想:网页通过添加一个 <script>
元素,向服务器请求 JSON 数据,服务器收到请求后,将数据放在一个指定名字的回调函数的参数位置传回来。
① 原生实现(JSONP 需要服务端的支持)
<script src='http://test.com/data?callback=func'></script> <!-- 向服务器 test.com 发出请求,该请求的查询字符串有一个 callback 参数,用来指定回调函数的名字 --> <!-- 给客户端返回数据 "func('+JSON.stringify(data)+')" ,浏览器把字符串变成 js 表达式执行 --> <!-- func 需要是一个全局函数 --> <script type='text/javascript'> function func(res){ // 处理获得的数据 } </script>
② jQuery 提供了 JSONP 的处理方式
$.ajax({ url: 'http://www.test.com:8000/login', type: 'get', dataType: 'jsonp',// 设置请求方式为 jsonp jsonpCallback: 'handleCallback',// 自定义回调函数名 data: {} })
③ Vue.js
this.$http.jsonp('http://www.test.com:8080/login', { params: {}, jsonp: 'handleCallback' }).then(res => { // });
2. CORS 跨域资源共享
- CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
- 它允许浏览器向跨源服务器,发出XMLHttpRequest
请求,从而克服了AJAX只能同源使用的限制。- 实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
3. 正向代理
正向代理:
1. 配置代理的第一种方式
在package.json中追加如下配置
"proxy":"http://localhost:5000"
说明:
- 优点:配置简单,前端请求资源时可以不加任何前缀。
- 缺点:不能配置多个代理,只适用配置一台服务器的情况。
- 工作方式:上述方式配置代理,当请求了3000不存在的资源时,那么该请求会转发给5000 (优先匹配前端资源)
2. 配置代理的第一种方式
第一步:创建代理配置文件
在src下创建配置文件:src/setupProxy.js
第二步:编写setupProxy.js配置具体代理规则:
const proxy = require('http-proxy-middleware')
module.exports = function(app) {
app.use(
proxy('/api1', { //api1是需要转发的请求(所有带有/api1前缀的请求都会转发给5000)
target: 'http://localhost:5000', //配置转发目标地址(能返回数据的服务器地址)
changeOrigin: true, //控制服务器接收到的请求头中host字段的值
/*
changeOrigin设置为true时,服务器收到的请求头中的host为:localhost:5000
changeOrigin设置为false时,服务器收到的请求头中的host为:localhost:3000
changeOrigin默认值为false,但我们一般将changeOrigin值设为true
*/
pathRewrite: {'^/api1': ''} //去除请求前缀,保证交给后台服务器的是正常请求地址(必须配置)
}),
proxy('/api2', {
target: 'http://localhost:5001',
changeOrigin: true,
pathRewrite: {'^/api2': ''}
})
)
}
说明:
- 优点:可以配置多个代理,可以灵活的控制请求是否走代理。
- 缺点:配置繁琐,前端请求资源时必须加前缀。