同源策略
什么是同源?在浏览器当前的窗口输入window.origin或者location.origin就可以得到当前的源,比如当前的源就是
源 = 协议 + 域名 + 端口号
如果两个url的协议,域名,端口号都是完全相同的,那么这两个url就是同源的。比如https://baidu.comh和https://www.baidu.com就是不同源的,只有完全一致妈才会死同源的url。对于两个不同源url,浏览器规定,如果JS运行在源A中,此时如果想要源B的数据,就必须进行跨域。这是浏览器的规定的,为了更好的保护用户的隐私。
如果没有同源
设想一下,如果没有同源会发生什么?比如qq空间,源为https://user.qzone.qq.com。 此时假设当前用户已经登录,AJAX请求/qqFriends.json(当前用户好友的数据)就可以得到数据。这一切看起来都很正常。此时黑客进行了入侵。假设其中一个好友发了一个钓鱼网站给用户,此时我点开网页,这个网页也请求你的/qqFriends.json。即https://uest.qzone.qq.com/friends.json 此时你的qq好友的列表就被黑客通过AJAX拿走了!
为什么会这样?
因为服务器没法区分发送者,qq空间的JS和钓鱼网站的JS发的请求几乎是没有任何区别的(refer不一样),此时如果后台没有检查refer,那数据就被拿走了。所以为了防止数据被顺走这种情况发生,浏览器采取了严格的同源策略————不同源的页面之间,不允许互相访问数据! 我们做个实验来看看这个情况。我们一个server,然后给不同的端口号,比如一个是8888,另一个是8889,此时在8888端口的服务器中请求一个js,js的内容是请求另一个端口的json数据。
else if (path === '/friends.json'){
response.statusCode = 200;
response.setHeader('Content-Type','text/json,charset="utf-8"')
response.write(fs.readFileSync("./public/friends.json"))
response.end()
}
得到报错 此时可以看到,请求已经发送成功了,但是并没有得到数据
小疑问:
1.为什么www.baidu.com访问baidu.com也算是跨域呢?
因为历史上,曾经出现过不同公司共用域名的情况,这个时候可能www.baidu.com和baidu.com可能并不是一个公司,为了安全起见,只要不同一律不同源
2.为什么端口不同也算跨域?
因为历史上服务器很少,很多时候一个端口一个公司,可能你们两个公司url完全一样,只是端口不同而已。
3.为什么跨域可以使用css,js和图片?
因为同源策略限制的是数据访问,我们引用css,js和图片的时候,我们只是在引用,并不知道他的内容
CORS
那么问题来了,怎么解决跨域,目前主流解决跨域方法的总共有两种,先介绍主流的一种:CORS。
其实浏览器作出同源策略的时候就给留了门,只要设置一个响应头:Access-Control-Allow-Origin
然后后面跟要跨域的网站就好了,这是MDN的详细文档
此时在我们的代码中加入这句话,发现我们得到了数据!
else if (path === '/friends.json'){
response.statusCode = 200;
response.setHeader('Access-Control-Allow-Origin',"*")
response.setHeader('Content-Type','text/json,charset="utf-8"')
response.write(fs.readFileSync("./public/friends.json"))
response.end()
}
此时问题得到了圆满的解决,但是有些浏览器并不支持CORS。
JSONP
对于IE浏览器的不支持CORS,前端工程师想出了JSONP的方法进行跨域。
- JSONP的思路
- 于是一个JSONP的步骤出来了
- 将要得到的数据写在同源的一个js中,取名friends.js
- 要进行跨域的网站用一个script标签引用这个friends.js
- 在要进行跨域的网站事先定义好一个函数,然后在friends.js中执行这个函数,并且执行时的参数就是要得到的数据
- 此时我们就通过这个回调函数得到了要得到的数
要得到数据的网站的js:
const script = document.createElement("script");
const num = parseInt(Math.random()*10)+1;
script.src = `http://localhost:8889/friends.js?callback=JSONP${num}`
document.head.appendChild(script)
script.onload = ()=>{
script.remove()
}
window[`JSONP${num}`] = (data)=>{
console.log(data);
}
friends.js
else if (path === '/friends.js'){
response.statusCode = 200;
response.setHeader('Content-Type','charset="utf-8"')
const data = fs.readFileSync('./public/friends.json')
let string = `window.xxx({{data}})`.replace('{{data}}',data).replace('xxx',query.callback)
response.write(string)
response.end()
}
面试中,可能会遇到一下的JSONP的问题,这是回答:
- JSONP是什么?
- 这个回调的名字是什么?
- JSONP的优缺点:
优点:1.兼容IE 2.可以跨域 缺点:1.不能获得AJAX的状态 2.只能发get请求
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!