云社区 博客 博客详情

一文搞懂浏览器同源策略

技术火炬手 发表于 2021-02-19 15:34:13 2021-02-19
0
0

【摘要】 同源策略就是指必须在同一个协议,域名,端口号下,而且三者必须一致的。

本文会从以下几个方面讲述同源策略:

  • 第一点 what:什么是同源策略
  • 第二点 why:为什么需要同源策略
  • 第三点 how:如何解决经典的跨域问题

什么是同源策略

什么是同源策略呢?通常一个概念出来之后,我会从生活的实际例子找到解析,你可以想象一下,假如你们家的房子,是不是不允许陌生人进入,如果可以随便进入,那么久有可能被盗了,那么这个时候,锁头和钥匙就出现了为了保证家的安全。

所以我们引出浏览器的同源策略,就是指必须在同一个协议,域名,端口号下,而且三者必须一致的。这个时候,我们就说是同源。

举个例子:

https://www.angular.cn:80/guide/inputs-outputs

  • http:// 是我们所说的协议。
  • www.angular.cn 是我们所说的域名。
  • 80 表示端口号。

所以就会牵引出一个问题,不同源的数据交互问题,如果是以下两个链接交互数据,可以通过同源策略的检测:

https://www.angular.cn:80/guide/inputs-outputs
	https://www.angular.cn:80/guide/index

而如果是以下这样的链接交互数据,则不能通过同源策略的检测:

http://www.child.a.com/test/index.html ----失败,域名不同
	https://www.a.com/test/index.html ----失败,协议不同
	http://www.a.com:8080/test/index.html ----失败,端口号不同

有哪些是不受同源策略限制

  • 页面上的链接,比如 a 链接。
  • 重定向。
  • 表单提交。
  • 跨域资源的引入,比如:script, img, link, iframe。

解决跨域问题

既然有同源策略的限制,那么就会产生跨域问题,就是指不同源的脚本在数据交互的时候,会报错,这个过程就是跨域。

那么有什么解决方案?

  • JSONP 解决跨域
  • CORS 解决跨域

总的来说,这两个比较经典,工作中比较常用,所以先讲讲上面的方案。

JSONP 解决跨域

什么是 JSONP,举个例子,就是 a.com/jsonp.html 想要获取 b.com/main.js 的数据,这个时候由于浏览器同源策略,是获取不到数据的,所以我们可以在 a.com/jsonp.html 创建一个 script 脚本,http://b.com/main.js?callback=xxx。在main.js中调用这个回调函数xxx,并且以JSON数据形式作为参数传递,完成回调。我们来看看代码:

	// a.com/jsonp.html中的代码
	  function addScriptTag(src) { 
	       var script = document.createElement('script'); 
	       script.setAttribute("type","text/javascript"); 
	       script.src = src; 
	      document.body.appendChild(script);
	  }
	  window.onload = function () { 
	      addScriptTag('http://b.com/main.js?callback=foo');
	  } //window.onload是为了让页面加载完成后再执行
	  function foo(data) { 
	        console.log(data.name+"欢迎您");
	  };
	 
	//b.com/main.js中的代码
	foo({name:"hl"})

存在以下几点问题:

  • 只能使用 GET 请求方式,无法使用 POST 请求方式。
  • 可能被注入恶意代码,篡改页面内容,可以采用字符串过滤来规避此问题。

CORS 解决跨域

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
刚才的例子中,在b.com里面添加响应头声明允许a.com的访问,代码:

	Access-Control-Allow-Origin: http://a.com

然后a.com就可以用ajax获取b.com里的数据了。

登录后可下载附件,请登录或者注册

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区),文章链接,文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件至:huaweicloud.bbs@huawei.com进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容。
评论文章 //点赞 收藏 0
点赞
分享文章到微博
分享文章到朋友圈

上一篇:终于搞懂了Python模块之间的相互引用问题

下一篇:改写if-else的几个思路

评论 (0)


登录后可评论,请 登录注册

评论