Twlig / issuesBlog

MIT License
3 stars 0 forks source link

跨域访问 #8

Open Twlig opened 2 years ago

Twlig commented 2 years ago

同源策略

同源策略是浏览器最核心也最基本的安全功能。保证用户信息的安全,防止恶意的网站窃取数据。对于不同源的站点之间的相互请求会做限制。

同源策略需同时满足的三个要求:

http:www.test.com与https:www.test.com 不同源——协议不同
http:www.test.com与http:www.admin.com 不同源——域名不同
http:www.test.com与http:www.test.com:8081 不同源——端口不同

如果非同源,共有三种行为受到限制:

  1. Cookie、LocalStorage 和 IndexDB 无法读取
  2. DOM 无法获得
  3. AJAX 请求不能发送

注意:跨域限制仅仅是浏览器的行为,通过代理服务器,或者其他工具发送请求就能轻松绕过

跨域流程

跨域请求类型

​ 浏览器在发送跨域请求的时候会判断一下是简单请求还是非简单请求,简单请求:先执行后判断是否跨域。非简单请求浏览器则会先发送一次OPTIONS预检请求,根据预检请求的结果,决定是否正式发送请求。

  1. 简单请求

    • 方法仅限于 HEAD,GET或POST
    • 无自定义头
    • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain (没有application/json, 如果发送JSON格式的body请求数据是一个非简单请求)
  2. 非简单请求

    除上述简单请求之外都是非简单请求

跨域解决方案

跨域问题在前端和后端都有解决方案。有以下两点值得注意:

  1. 如果是协议和端口造成的跨域问题“前台”是无能为力的
  2. 在跨域问题上,域仅仅是通过“URL的首部”来识别而不会去尝试判断相同的IP地址对应着两个域或两个域是否在同一个IP上

前端解决方案

  1. document.domain + iframe跨域

    此方案仅限主域相同,子域不同的跨域应用场景。实现原理:两个页面都通过JS强制设置document.domain为基础主域,就实现了同域。

  2. location.hash + iframe跨域

    实现原理: a与b跨域相互通信,通过中间页c来实现。 三个页面,不同域之间利用iframe的location.hash传值,相同域之间直接JS访问来通信。

    具体实现:A域:a.html -> B域:b.html -> A域:c.html,a与b不同域只能通过hash值单向通信,b与c也不同域也只能单向通信,但c与a同域,所以c可通过parent.parent访问a页面所有对象

  3. window.name + iframe跨域

    window.name属性的独特之处:name值在不同的页面(甚至不同域名)加载后依旧存在,并且可以支持非常长的 name 值(2MB)

    通过iframesrc属性由外域转向本地域,跨域数据即由iframewindow.name从外域传递到本地域。这个就巧妙地绕过了浏览器的跨域访问限制,但同时它又是安全操作。

  4. postMessage跨域

    postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题:

    • 页面和其打开的新窗口的数据传递
    • 多窗口之间消息传递
    • 页面与嵌套的iframe消息传递
    • 上面三个场景的跨域数据传递

    用法postMessage(data,origin)方法接受两个参数:

    • data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
    • origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。
  5. 动态创建script

    script标签不受同源策略的限制

  6. 代理服务器

    由于同源策略是对浏览器和外域服务器的限制,如果是代理到本地服务器处理,然后由本地服务器与外域服务器通信,再由本地服务器转向浏览器,就可以绕过同源策略。处理的方法有Vue设置代理,或者Nginx,或者后端设置一个代理都可以。

  7. jsonp

    jsonp的原理就是利用 Githubissues.

  8. Githubissues is a development platform for aggregating issues.