什么是跨域
当一个URL的协议、端口、域名任何一个与当前URL不同就是跨域。
为什么会出现跨域
这是由于浏览器的同源策略,它是浏览器最核心的最基本的安全功能,没有同源策略,浏览器的正常功能就会受到影响,web就是建立在同源策略的基础之上,同源策略会阻止一个新的域的JavaScript脚本和另一个域的主机进行交互,同源就是能在一个域的两个页面具有相同的协议、域名和端口号。
JSONP解决跨域
JSONP是服务器与客户端通信的常用方法,可以兼容IE,但就是不支持post请求。
- 原生
<script src="http://test.com/data.php?callback=dosomething"></script>
向服务器test.com发出请求,该请求的查询字符串有一个callback参数,用来指定回调函数的名字
// 处理服务器返回回调函数的数据
<script type="text/javascript">
function dosomething(res){
// 处理获得的数据
console.log(res.data)
}
</script>
- JQuery
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
dataType: 'jsonp', // 请求方式为jsonp
jsonpCallback: "handleCallback", // 自定义回调函数名
data: {}
})
- Vue.js
this.$http.jsonp('http://www.domain.com:8080/login', {
params: {},
jsonp: 'handleCallback'
}).then((res) => {
console.log(res);
})
CORS解决跨域
CORS是跨域资源共享的缩写,是W3C的标准。
- 如果是普通的跨域请求,只要在服务端设置Access-Control-Allow-Origin
- 带cookie的话,前后端都要进行设置
- 原生
var xhr = new XMLHttpRequest(); // IE8/9需用window.XDomainRequest兼容
// 前端设置是否带cookie
xhr.withCredentials = true;
xhr.open('post', 'http://www.domain2.com:8080/login', true);
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
}
- JQuery
$.ajax({
url: 'http://www.test.com:8080/login',
type: 'get',
data: {},
xhrFields: {
withCredentials: true // 前端设置是否带cookie
},
crossDomain: true, // 会让请求头中包含跨域的额外信息,但不会含cookie
});
- Vue.js中的axios
axios.defaults.withCredentials = true;
- 服务端的后台需要设置Access-Control-Allow-Origin
window.postMessage()解决跨域
它可以解决:
- 页面和打开的窗口的数据传递
- 多窗口数据传递
- 页面和嵌套的iframe传递
- 跨域数据传递
// 父窗口打开一个子窗口
var openWindow = window.open('http://test.com', 'title');
// 父窗口向子窗口发消息(第一个参数代表发送的内容,第二个参数代表接收消息窗口的url)
openWindow.postMessage('Nice to meet you!', 'http://test.com')
调用message事件,监听对方发送的消息
// 监听 message 消息
window.addEventListener('message', function (e) {
console.log(e.source); // e.source 发送消息的窗口
console.log(e.origin); // e.origin 消息发向的网址
console.log(e.data); // e.data 发送的消息
},false);
proxy解决跨域
module.exports = {
devServer: {
proxy: {//解决跨域问题
'/api': {
// 此处的写法,目的是为了 将 /api 替换成 https://atimap.cn/
target: 'https://atimap.cn/',
// 允许跨域
changeOrigin: true,
ws: true,
pathRewrite: {
'^/api': ''
}
}
},
}
}