面试题跨域

Posted ThinkerWing

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了面试题跨域相关的知识,希望对你有一定的参考价值。

【面试题】跨域

https://www.ruanyifeng.com/blog/2016/04/same-origin-policy.html
https://juejin.cn/post/6844903972742889480#heading-10

同源策略

概念
同源策略:同端口、同域名、同协议

选择题:下列是否符合同源策略
http://www.example.com/dir2/other.html:同源
http://example.com/dir/other.html:不同源(域名不同)
http://v2.www.example.com/dir/other.html:不同源(域名不同)
http://www.example.com:81/dir/other.html:不同源(端口不同)

目的
同源政策的目的,是为了保证用户信息的安全,防止恶意的网站窃取数据。
设想这样一种情况:A网站是一家银行,用户登录以后,又去浏览其他网站。如果其他网站可以读取A网站的 Cookie,会发生什么?

很显然,如果 Cookie 包含隐私(比如存款总额),这些信息就会泄漏。更可怕的是,Cookie 往往用来保存用户的登录状态,如果用户没有退出登录,其他网站就可以冒充用户,为所欲为。因为浏览器同时还规定,提交表单不受同源政策的限制。

由此可见,"同源政策"是必需的,否则 Cookie 可以共享,互联网就毫无安全可言了。

localhost 和 127.0.0.1 虽然都指向本机,但也属于跨域。

限制范围
"同源政策"越来越严格。目前,如果非同源,共有三种行为受到限制

(1) Cookie、LocalStorage 和 IndexDB 无法读取。

(2) DOM 无法获得。

(3) AJAX 请求不能发送。

不存在跨域的情况(无视同源策略)

服务端请求服务端不存在跨域(浏览器请求服务器才存在同源策略)
< img src="跨域的图片地址"> (<img>标签的 src 属性不存在跨域)
<link href="跨域的css地址"> (<link>标签的 href 属性不存在跨域)
<script src="跨域的js地址"></script> (<script>标签的 src 属性不存在跨域)

跨域常见的方法

  • JSONP
  • WebSocket
  • CORS

JSONP

JSONP是服务器与客户端跨源通信的常用方法。最大特点就是简单适用,老式浏览器全部支持,服务器改造非常小。

它的基本思想是,网页通过添加一个<script>元素,向服务器请求JSON数据,这种做法不受同源政策限制;服务器收到请求后,将数据放在一个指定名字的回调函数里传回来。

首先,网页动态插入<script>元素,由它向跨源网址发出请求。

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://example.com/ip?callback=foo');


function foo(data) 
  console.log('Your public IP address is: ' + data.ip);
;

上面代码通过动态添加<script>元素,向服务器example.com发出请求。注意,该请求的查询字符串有一个callback参数,用来指定回调函数的名字,这对于JSONP是必需的。

JSONP(get形式)

问:为什么jsonp只支持get请求?

JSONP 是一种【请求一段 JS 脚本,把执行这段脚本的结果当做数据】的玩法。

所以,你能 POST 一段通过 script 标签引入的脚本吗?

(如果看过 JSONP 库的源码就知道,常见的实现代码其实就是 document.createElement(‘script’) 生成一个 script 标签,然后插 body 里而已。在这里根本没有设置请求格式的余地)。

所以JSONP的实现原理就是创建一个script标签, 再把需要请求的api地址放到src里. 这个请求只能用GET方法, 不可能是POST

原理:
利用<script>标签没有跨域限制的漏洞,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以
优缺点

1.优点
1.1它不像XMLHttpRequest对象实现的Ajax请求那样受到同源策略的限制,JSONP可以跨越同源策略;
1.2它的兼容性更好,在更加古老的浏览器中都可以运行,不需要XMLHttpRequest或ActiveX的支持
1.3在请求完毕后可以通过调用callback的方式回传结果。将回调方法的权限给了调用方。这个就相
当于将controller层和view层终于分开了。我提供的jsonp服务只提供纯服务的数据,至于提供服务以
后的页面渲染和后续view操作都由调用者来自己定义就好了。如果有两个页面需要渲染同一份数据,
你们只需要有不同的渲染逻辑就可以了,逻辑都可以使用同 一个jsonp服务。
2.缺点
2.1它只支持GET请求而不支持POST等其它类型的HTTP请求
2.2它只支持跨域HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
2.3 jsonp在调用失败的时候不会返回各种HTTP状态码。
2.4缺点是安全性。万一假如提供jsonp的服务存在页面注入漏洞,即它返回的javascript的内容被人控制
的。那么结果是什么?所有调用这个 jsonp的网站都会存在漏洞。于是无法把危险控制在一个域名下…
所以在使用jsonp的时候必须要保证使用的jsonp服务必须是安全可信的。

WebSocket

WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com

上面代码中,有一个字段是Origin,表示该请求的请求源(origin),即发自哪个域名。

正是因为有了Origin这个字段,所以WebSocket才没有实行同源政策。因为服务器可以根据这个字段,判断是否许可本次通信。

CORS

问:CORS与JSONP的比较

CORS与JSONP的使用目的相同,但是比JSONP更强大。

JSONP只支持GET请求,CORS支持所有类型的HTTP请求。JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。

问:什么是CORS?

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

如果wang.com和ergou.com这两个网站都是我的,我就是想让wang.com去访问ergou.com里面的数据应该怎么办呢?
只需要wang.com在响应头里写ergou.com可以访问即可。这就是CORS。
实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

问:CORS存在的问题

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

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

请求方式为HEAD、POST 或者 GET
http头信息不超出以下字段:Accept、Accept-Language 、 Content-Language、 Last-Event-ID、 Content-Type(限于三个值:application/x-www-form-urlencoded、multipart/form-data、text/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实现跨域请求的一个弊端。

选择题

1. 解决跨域的方案,以下说法对的是
A、可以利用flash的http请求,来处理跨域问题
B、通过iframe设置document.domain可以实现跨域
C、一般情况下,m.toutiao.com可以ajax请求www.toutiao.com域名下的接口并获得响应
D、通过jsonp方式可以发出post请求其他域名下的接口

正确答案:B

解析:

B、站内AJAX跨域可以通过document.domain和iframe实现,document.domain;这种方式用在主域名相同子域名不同的跨域访问中
C、同源策略
DJSONP的缺点则是:它只支持GET请求而不支持POST等其它类型的HTTP请求;它只支持跨域
HTTP请求这种情况,不能解决不同域的两个页面之间如何进行JavaScript调用的问题。
2. 解决跨域的方案,以下说法对的是
A、如果接口为post请求,后端人员将接口的method改为get可以解决
B、jsonp的内部是ajax实现的
C、建议在线上使用webpack devServer proxy解决
D、建议线上接口修改nginx增加header头解决

正确答案:C

B、jsonp请求;jsonp的原理是利用<script>标签的跨域特性,可以不受限制地从其他域中加载资源,类似的标签还有<img>.
JSONP 核心原理script 标签不受同源策略影响。动态插入到 DOM 中的 script 脚本可以立即得到执行。和ajax没有关系。
D、nginx做反向代理用的,响应头的设置是后端

以上是关于面试题跨域的主要内容,如果未能解决你的问题,请参考以下文章

Nginx以及JSONP跨域ajax请求面试题

Nginx以及JSONP跨域ajax请求面试题

Nginx以及JSONP跨域ajax请求面试题

一篇文章搞明白CORS跨域

一篇文章搞明白CORS跨域

跨域请求如何携带cookie?不小心都拿了Offer