欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【面试题】跨域

程序员文章站 2022-03-02 14:45:43
...

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做反向代理用的,响应头的设置是后端