网上那么多总结,你理清楚了嘛
跨域的三种方式
什么是同源
若两个url的域名 + 协议 + 端口号都相同,那么称这两个url同源。非同源的客户端脚本在没有明确授权的情况下,不能读写对方资源,在请求数据时,浏览器会在控制台中报一个异常,提示拒绝访问。1
2
3
4
5
6
7
8
9
10
11
12
13
14http://store.company.com/dir/page.html
同源、不同路径:
http://store.company.com/dir/other.html
http://store.company.com/dir/inner/another.html
协议不同:
https://store.company.com/secure.html
域名不同:
http://news.company.com/dir/other.html
端口不同:
http://store.company.com:81/dir/etc.html
什么是跨域
跨域指不同源之间的资源访问,只要请求的url在域名、协议或端口有不同,那么就属于跨域。跨域限制是浏览器自带的安全机制,只有在浏览器上发生跨域请求时,就会抛出错误。
JSONP(JSON+padding)
- 使用场景:当前浏览器不支持CORS(一般是IE),需要别的方式实现跨域
- JSONP的实现逻辑:通过请求一个js文件(动态添加script标签),这个js文件中有一个回调函数,回调函数中包含了我们需要的数据。回调函数的名字可以是随机生成的一个随机数,前端需要将这个回调函数的名字以callback的参数传回给后台,后台会将这个函数返回并执行
- 优点:作用是跨域且支持IE浏览器
- 缺点:不能像ajax那样知道精确的状态(不知道状态码、响应头),只知道请求是成功或失败(因为函数监听的是onload和onerror事件);另外script标签的src属性只支持GET不支持POST
下面是一个模拟的过程:
请求方:frank.com 的前端程序员(浏览器)
响应方:jack.com 的后端程序员(服务器)
1、请求方创建 script 标签,src 指向响应方,同时传一个查询参数 ?callbackName=yyy
2、响应方根据查询参数callbackName,构造形如
yyy.call(undefined, ‘你要的数据’)
yyy(‘你要的数据’)
这样的响应
3、浏览器接收到响应,就会执行 yyy.call(undefined, ‘你要的数据’)
4、那么请求方就知道了他要的数据
示例
HTML 中 script 标签可以加载其他域下的js,比如我们经常引入一个其他域下线上cdn的jQuery1
<script src="http://api.jirengu.com/weather.php"></script>
这时候会向天气接口发送请求获取数据,获取数据后做为 js 来执行。 但这里有个问题,数据是 JSON 格式的数据,直接作为 JS 运行的话我如何去得到这个数据来操作呢?
于是我们添加一个callback的参数1
<script src="http://api.jirengu.com/weather.php?callback=showData"></script>
这个请求到达后端后,后端会去解析callback这个参数获取到字符串showData,在发送数据做如下处理:
之前后端返回数据是: {“city”: “hangzhou”, “weather”: “晴天”} 现在后端返回数据: showData({“city”: “hangzhou”, “weather”: “晴天”}) 前端script标签在加载数据后会把 showData({“city” “hangzhou”, “weather”: “晴天”})做为 js 来执行,这实际上就是调用showData这个函数,同时参数是 {“city” “hangzhou”, “weather”: “晴天”}。 用户只需要提前在页面定义好showData这个全局函数,在函数内部处理参数即可。
1 | <script> |
前后端完整示例
前端代码1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17button.addEventListener('click', (e)=>{
let script = document.createElement('script')
let functionName = 'frank'+ parseInt(Math.random()*10000000 ,10)
window[functionName] = function(){ // 每次请求之前搞出一个随机的函数
amount.innerText = amount.innerText- 1
}
script.src = '/pay?callback=' + functionName
document.body.appendChild(script)
script.onload = function(e){ // 状态码是 200~299 则表示成功
e.currentTarget.remove()
delete window[functionName] // 请求完了就干掉这个随机函数
}
script.onerror = function(e){ // 状态码大于等于 400 则表示失败
e.currentTarget.remove()
delete window[functionName] // 请求完了就干掉这个随机函数
}
})
后端代码,不用看1
2
3
4
5
6
7
8
9
10
11
12
13...
if (path === '/pay'){
let amount = fs.readFileSync('./db', 'utf8')
amount -= 1
fs.writeFileSync('./db', amount)
let callbackName = query.callback
response.setHeader('Content-Type', 'application/javascript')
response.write(`
${callbackName}.call(undefined, 'success')
`)
response.end()
}
...
jQuery的写法
1 | $(Button).on('click', function () { |
CORS跨域
跨源资源分享(Cross-Origin Resource Sharing),是一种ajax跨域请求资源的方式。实现方式很简单,当你使用XMLHttpRequest发送请求时,浏览器发现该请求不符合同源策略,会给该请求加一个请求头:Origin,后台进行一系列处理,如果确定接受请求则在返回结果中加入一个响应头:Access-Control-Allow-Origin; 浏览器判断该相应头中是否包含 Origin 的值,如果有则浏览器会处理响应,我们就可以拿到响应数据,如果不包含浏览器直接驳回,这时我们无法拿到响应数据。所以 CORS 的表象是让你觉得它与同源的 ajax 请求没啥区别,代码完全一样。1
2response.setHeader('Access-Control-Allow-Origin','http://jayce.com:8003')
response.setHeader('Access-Control-Allow-Origin','*') // *代表允许所有浏览器访问
postMessage
作用:用于网页间通讯
语法:otherWindow.postMessage(message, targetOrigin);
otherWindow:指目标窗口,也就是给哪个window发消息,是 window.frames 属性的成员或者由 window.open 方法创建的窗口
message: 是要发送的消息,类型为 String、Object
targetOrigin: 是限定消息接收范围,可以是*(无限制)或者一个URL
例如父窗口 http://aaa.com 向子窗口 http://bbb.com 发送消息1
2var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');
子窗口向父窗口发送消息也是类似1
window.opener.postMessage('Nice to see you', 'http://aaa.com');
cookie、session及localStorge
说说cookie和localStorage的区别吧!这个几乎每次面试都会被提一嘴的问题