前端通讯|同源|跨域
akong 2018-12-15 21:30:23 前端通讯同源跨域
来梳理一下关于前端通讯的知识,包括同源策略,前后端如何通讯,以及跨域的几种方式。
# 前端通讯相关
# 同源策略
MDN上对同源策略的解释:
同源策略限制了从同一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的重要安全机制。
- 源包括 协议 域名 端口 三者有一个不同,那就是不同源,也就是跨域。
- **限制:**不同源的文档没有权利相互操作
- Cookie,LocalStorage,和 IndexDB 无法获取
- Dom无法获取
- AJAX不能发送
# 前后端如何通讯
- Ajxa 同源通讯
- WebSocket
- CORS
# 创建Ajax
- XMLHttpResquest对象的工作流程
- 兼容性处理
- 事件的触发条件
- 事件的触发顺序
function success(text) {
var textarea = document.getElementById('test-ie-response-text');
textarea.value = text;
}
function fail(code) {
var textarea = document.getElementById('test-ie-response-text');
textarea.value = 'Error code: ' + code;
}
// 考虑兼容创建ajax对象
var request = XMLHttpRequest
? new XMLHttpRequest()
:new ActiveXObject('Microsoft.XMLHTTP')
request.onreadystatechange = function () { // 状态发生变化时,函数被回调
if (request.readyState === 4) { // 成功完成
// 判断响应结果:
if (request.status === 200) {
// 成功,通过responseText拿到响应的文本:
return success(request.responseText);
} else {
// 失败,根据响应码判断失败原因:
return fail(request.status);
}
} else {
// HTTP请求还在继续...
}
}
// 发送请求:
request.open('GET', '/api/categories');
request.send();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 跨域方式
# Jsonp
原理:
使用script标签的异步加载来实现
大致流程:
通过前端页面加载script标签后加参数和callback名,
例如<script>http://abc.com/?query&callback=akong</script>
后端收到请求,返回后端中akong
对应的方法给前端,即可实现通讯
允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。
实例:
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
// 得到航班信息查询结果后的回调函数
var lookAK = function (data) {
alert('你查询的阿孔信息结果是:身高 ' + data.height + ' 米,' + '体重 ' + data.weight + ' 吨');
};
// 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码)
var url = "http://akong.jsonp.js?callback=lookAk";
// 创建script标签,设置其属性
var script = document.createElement('script');
script.setAttribute('src', url);
// 把script标签加入head,此时调用开始
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</body>
</html>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
js
lookAk({
"heith": "145",
"weight": 160
})
1
2
3
4
2
3
4
# Hash
hash改变 页面不刷新
seach改变 页面刷新
// 现有两个跨域窗口A,B
// 在A窗口内拼接scr+要传递的数据
var B = document.getElementsByTagName('iframe')
B.src = B.src + '#' + 'data'
// 在B中接受
window.onhashchange = function () {
var data = window.location.hash
//...
//处理data
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# postMessage
h5中定义的新标准
// 窗口A向窗口B跨域发送消息
// A窗口下代码
Bwindow.postMessage('data','http://B.com')
// 在B中监听
window.addEventListener('message',function (event) {
console.log(event.origin) // http://A.com
console.log(event.source) // Awindow
console.log(event.data) // data
},false)
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# WebSocket
var ws = new WebSocket('wws//a.com')
ws.open = function (e) {
console.log('已连接')
ws.send('hello~')
}
ws.onmessage = function (e) {
console.log('收到消息:'+e.data)
ws.close()
}
ws.onclose = function (e) {
console.log('已关闭')
}
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# CORS
相当于支持跨域通讯的AJax
他会在请求头中加上 Origin 项,使其支持跨域
fetch('/url',{
method:'get',
Origin: '....'
}).then(function(response){
...
}).catch(function (err) {
// 抓错
})
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8