点击上方 好好学java ,选择 星标 公众号

重磅资讯、干货,第一时间送达
今日推荐:是时候扔掉Postman了,又一个被低估的IDEA插件出来了...个人原创+1博客:点击前往,查看更多
作者:前端求职中_杭州_感谢内推
链接:https://juejin.im/post/5e74e690e51d4526d87c93df

同源策略

在说跨域之前,首先需要了解的一个概念就是”同源策略“

什么是源?

源=协议+域名+端口号。

如果两个url的协议、域名、端口号完全一致,那么这两个url就是同源的。

我们可以通过window.originlocation.origin得到当前源。

https://wang.com
https://ergou.com
//不同源,域名不一致(记住:只有完全一模一样才算同源)http://wang.com/index.html
http://wang.com/server.php
//同源localhost 调用 127.0.1
//不同源

什么是同源策略?

同源策略即:不同源之间的页面,不准互相访问数据。

浏览器规定:如果JS运行在源A里,那么就只能获取源A的数据,不能获取源B的数据,即不允许跨域。

假设 wang.com/index.html引用了ergou.com/1.js,那么就说1.js运行在源wang.com

注意,这和ergou.com没有关系,虽然1.js是从它那里下载的.

所以1.js就只能获取wang.com的数据,这就是浏览器的功能,浏览器就是故意这样设计的。

为什么会有同源策略?

之所以需要使用同源策略,就是为了保护用户的隐私。

以微信为例,源为 https://user.weixin.com,假设当前用户已经登录,并且AJAX请求 /friends.json 可以获取用户好友列表。

这个时候黑客来了,他把 https://user-winxin.com分享给你,实际上这是一个钓鱼网站,你点开这个网页,这个网页也请求你的好友列表 https://user.weixin.com/friends.json。

请问,这个时候你的好友列表是不是就被黑客给偷走了?

问题的根源

之所以会出现这个问题,其根源就在于无法区分发送者

微信里面的JS和黑客的JS发送到请求几乎没有区别(referer区别)

但是如果后台的开发者没有检查 referer,那么就完全没有区别。

所以,如果没有同源策略,任何页面都能偷走微信里面的数据,甚至是支付宝里面的余额。

安全原则

有的小伙伴可能会问,既然referer有区别,那检查referer不就好了?

安全原则:安全链条上的强度取决于安全链条上最弱的一环。

同时,万一这个网站的后端开发者是一个傻叉呢?

所以浏览器应该主动预防这种偷数据的行为。

总之,为了保护用户的隐私,浏览器设置了严格的同源策略。

如果浏览器不限制跨域,一定是这个浏览器出现了bug

跨域

什么是跨域?

跨域,即浏览器试图执行其他网站的脚本。但是由于同源策略的限制,导致我们无法实现跨域。

关于跨域的几个问题

为什么a.wang.com访问wang.com也算跨域?

因为历史上,出现过不同的公司共用域名,a.wang.comwang.com不一定是同一个网站,浏览器谨慎起见,认为这是不同的源。

为什么不同端口也算跨域?

原因同上,一个端口一个公司的情况也不是没有的。

记住:安全链条的强度取决于最弱的一环,所有和安全相关的问题都要谨慎对待。

为什么两个网站的IP一样,也算跨域?

原因同上,因为IP也是可以共用的。

为什么可以跨域使用CSSJS和图片等?

同源策略限制的是数据访问,我们引用CSSJS和图片的时候,其实并不知道其内容,我们只是在引用。

CORS跨域

什么是CORS?

CORS的全称是"跨域资源共享"(Cross-origin resource sharing)。 它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

如何理解CORS?

如果wang.comergou.com这两个网站都是我的,我就是想让wang.com去访问ergou.com里面的数据应该怎么办呢?

只需要wang.com在响应头里写ergou.com可以访问即可。这就是CORS

实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

两种请求

CORS跨域分为两种请求,一种是简单请求,另外一种就是复杂请求

简单请求

只要满足以下条件的就是简单请求:

  • 请求方式为HEADPOST 或者 GET

  • http头信息不超出以下字段:AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type(限于三个值:application/x-www-form-urlencodedmultipart/form-datatext/plain)

简单请求的实现具体来说就是在信息头中加入一个Origin字段:

GET /cors HTTP/1.1
Origin: http://wang.com
Host: api.ergou.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0
...

Origin的作用就是用来说明本次请求来自哪个源,服务器会根据Origin的值来判断是否接受本次请求。

如果Origin所表示的源不被服务器接受,即浏览器发现回应的信息头中没有Access-Control-Allow-Origin字段,就会自动抛出一个错误。

注意:这种错误是无法通过状态码识别的,这也是通过CORS实现跨域请求的一个弊端。

如果Origin所表示的源被服务器端所接受,那么服务器就会返回如下响应:

Access-Control-Allow-Origin: http://api.ergou.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
  • Access-Control-Allow-Origin :该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求

  • Access-Control-Allow-Credentials: 该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。(注意:如果要发送cookie,不仅要进行上述的设置,还要在AJAX请求中设置withCredentials属性)

  • Access-Control-Expose-Headers:该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。

复杂请求

所谓复杂请求,即不满足上述条件的请求就是复杂请求。

比如请求的方法是PUTDELETE,或者Content-Type字段的类型是application/json

复杂请求首先会发起一个预检请求,该请求是 option 方法的,通过该请求来知道服务端是否允许跨域请求。

var url = 'http://api.wang.com/cors';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();

上面的请求就是一个复杂请求,当浏览器发现这是一个复杂请求之后,就会主动发出一个预检请求,询问服务器是否允许本次请求。

服务器收到预检请求之后,检查了OriginAccess-Control-Request-MethodAccess-Control-Request-Headers字段以后,确认允许跨源请求,才会做出相应的回应。

Access-Control-Allow-Origin: http://api.wang.com
Content-Type: text/html; charset=utf-8

CORS存在的问题

不支持IE8/9,如果要在IE8/9使用CORS跨域需要使用XDomainRequest对象来支持CORS

JSONP跨域

什么是JSONP?

我们在跨域的时候由于当前的浏览器不支持 CORS 或者因为某些条件不支持 CORS,我们必须使用另外一种方式来跨域,于是我们就请求一个 JS 文件,这个 JS 文件会执行一个回调,回调里面就有我们需要的数据。

let script = document.createElement('script');script.src = 'http://www.wang.cn/login?username=wang&callback=callback';document.body.appendChild(script);function callback(res) {console.log(res);
}

回调函数的名字是什么?

回调的名字是可以随机生成的的一个随机数,我们把这个名字当成 callback 的参数传给后台,后台会把这个函数再次返回给我们并执行

JSONP跨域优点

  • 兼容ie

  • 可以跨域

JSONP跨域缺点

  • 由于是 script 标签,所以读不到 ajax 那么精确的状态,不知道状态码是什么,也不知道响应头是什么,它只知道成功和失败。

  • 不支持post(因为是 script 标签,所以只支持 get 请求)

告诫自己,即使再累也不要忘记学习,成功没有捷径可走,只有一步接着一步走下去。 共勉!

3000 字说说跨域!面试官听完之后露出了满意的笑容相关推荐

  1. 朋友圈怎么设计测试用例,面试官听完都惊呆了

    (资深面试官,每天更新常问面试题,内含100个用例设计) 姐妹们,大家在面试前都花了很多时间精力收集题目.但我想温柔的提醒:粗制滥造的答案不仅对面试毫无帮助,反而会浪费宝贵的面试机会.很多姐妹就找着这 ...

  2. 干加个偏旁可以变成什么字_面试官:“干”字加一笔,变成什么字?回答王和午字不对...

    随着大学生的增多,如今的求职者进入职场,想到一份心仪的工作,最让人头疼的就是面试,越来越多的企业都需要全能型的人才,从而在面试的时候不仅要考核专业知识,面试官还要费尽心思出各种各样的题来考验求职者们的 ...

  3. 跟Java面试官对线的一天!唬住就要50K,唬不住就要5K

    个人面经 前言 JVM篇 计网篇 Java基础篇 多线程篇 Spring框架篇 MyBatis框架篇 MySQL篇 Redis篇 分布式.微服务篇 小结 前言 不积跬步无以至千里,不积小流无以成江海 ...

  4. 美团四面 Java 岗,终获 offer,我是这么回答面试官的

    前言 经历了 10 月的疫情挣扎与 11 月失业的煎熬,终于来到了春末的 12 月,内心的压力也稍稍的松懈了一些,终于可以放心找个工作了,可是随着的等待面试的机会的越来越少,这份焦虑反而越来越大,也偶 ...

  5. 奇葩面试大赏:四年没见的前女友成了我的面试官

    看着正常人,实则奇葩魂. 面试,是每一个职场人都难以绕开的话题.无论你是初出茅庐的应届毕业生,还是久经沙场的职场老将,都或多或少有过一些印象深刻的面试经历. 我们在面试过程中自我迭代的同时,也不断刷新 ...

  6. 从面试官角度告诉大家如何准备项目方面的描述

    之前写了篇博文,你的简历能帮你争取到面试机会吗,反响不错,也承蒙管理员抬爱,放在首页,为了答谢大家,在这篇博文里,我来分享些如何准备和叙述项目经验的技巧. 本文的内容是根据java web轻量级开发面 ...

  7. 面试后要请你吃饭_面试官:老板请吃饭,却要你结账,你会咋做?男子智答,被录用...

    原创不易,转载请注明 坚持弘扬社会正能量 面试官:老板请吃饭,却要你结账,你会咋做?男子智答,被录用 出门在外打工,平时和朋友一起吃个饭很正常,,毕竟大家在同一座城市上班,这样你来我往的可以增加朋友之 ...

  8. 别慌,不就是跨域么!

    2019独角兽企业重金招聘Python工程师标准>>> 原文出处: Neal_yang 前端开发中,跨域使我们经常遇到的一个问题,也是面试中经常被问到的一些问题,所以,这里,我们做个 ...

  9. [前端面试经]百度和好未来的面试官把我榨干了

    百度和好未来的面试官把我榨干了 我,普通本科计算机专业,18年6月毕业,抛去实习,工作经验只有一年半,没想到自己临时的决定让我敲开了百度的大门,非常荣幸地成为百度的RD. 2019年最后一个月,由于当 ...

最新文章

  1. 讯飞语音语音听写,设置识别语言
  2. 一则利用内核漏洞获取root权限的案例【转】
  3. 通过maven创建自己的archetype
  4. 【Spring】Bean的生命周期
  5. C#中JSON的理解
  6. 谷歌控制面板中的NetWrok
  7. sql server charindex函数和patindex函数详解(转)
  8. P53:进化了8亿年的抑癌基因
  9. 微软ASP.NET AJAX框架剖析
  10. Java之序列化和反序列化
  11. Python基于周立功ZCANPRO开发刷写脚本
  12. python 画三角函数_如何用python表示三角函数
  13. Android JOSON应用及详解
  14. 从贫穷到富有——我的修行之路
  15. 毕业设计 stm32车牌识别系统设计与实现 - 单片机 嵌入式
  16. php把数组作为函数参数传递,使用关联数组作为函数的参数《 PHP 基础 》
  17. python导出百万数据到excel_使用python将大量数据导出到Excel中的小技巧分享
  18. QT学习(六)——Lamda表达式的使用
  19. table和div的比较
  20. 第九届广东省大学生程序设计竞赛排名

热门文章

  1. VC从文件中加载图片
  2. asp.net 上传大文件解决方案(转)
  3. opencv-4.1.0-百度云盘下载链接-环境配置
  4. 低功耗蓝牙BLE对应Gatt的UUID
  5. STM32之中断与事件---中断与事件的区别
  6. 全志V3S代码中的bug之1
  7. java新建测试程序_java – 如何创建一个CloseableHttpResponse对象来帮助测试?
  8. java面试题(java基础)
  9. buu [AFCTF2018]Morse
  10. [How TO]-ubuntu20.10上安装Pulse Secure客户端