关于同源策略

最近挖洞总是遇到CORS之类的,索性就再次了解下同源策略

介绍

说到同源策略,经常会有这么一张图

那我们从头分析这是个什么意思

  • 第一个是http协议,而第三个是https协议,协议不同
  • 第一个是80端口,第四个是81端口,端口不同
  • 第一个的主机名是store.company.com,第五个的是news.company.com,不同主机名
    也就是说只有协议端口主机名,都相同的情况下才满足同源策略
    那么这有什么用呢?当然是在某种程度上减轻了恶意脚本执行造成的危害,举个栗子
    A登陆了a.com,并且在新的标签页打开了有恶意读取Cookie的b.com,这个时候由于同源策略,a.com的CooKie就不会被读取到
    a网站
    1
    2
    3
    <?php
    setcookie("Cookie","admin");
    echo "<script>alert(document.cookie);</script>";

    b网站
    1
    <script>alert(document.cookie);</script>

当a.com想要调用b.com的API的时候同源策略也会进行阻止

1
2
3
4
5
6
7
8
9
10
<script type="text/javascript">
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if(xhr.readyState === 4) {
console.log(xhr.responseText);
}
}
xhr.open("GET", "http://b.com/get?id=1");
xhr.send();
</script>

跨域请求

刚刚还在说禁止跨域,怎么现在就出现了跨域请求呢?
一般而言,网络请求可以大体分为三类

  • 跨域写,通常被允许,像重定向,提交表单之类的都属于这个了
  • 跨域嵌入,通常被允许,像<script>,<link>,<img> 之类的都是允许的
  • 跨域读,通常被禁止,但是脚本还是执行了,只不过禁止读取回复
    同源策略影响范围包括:普通的HTTP请求、XMLHttpRequest、XSLT、XBL。

CORS

CORS又是什么东西呢?上面已经提到,在嵌入外域数据时,同源策略并不会起到作用,但是,XMLHttpRequest就有些难受啦
,只能发送数据,但是不能查看返回信息,当然,CSRF的话只要发送数据成功就已经OK啦,而CORS 策略,则是允许 Web 应
用程序进行跨域访问
CORS通过一些特殊的 HTTP 头来确保哪些源站可以请求哪些资源
通常而言,在跨域前会发送一个OPTIONS头的请求包,如果请求包内容检查通过,才会发送真正的请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
OPTIONS /c HTTP/1.1
Host: b.a.com
Connection: close
Origin: http://b.a.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type


HTTP/1.1 200 OK
Date: Fri, 15 Feb 2019 14:50:45 GMT
Server: Tengine
Access-Control-Allow-Origin: http://*.a.com
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

先来看请求头,其中的Origin表示发起请求的主机名,而返回头中有一个Access-Control-Allow-Origin,如果请求的Origin不在这个范围内,检查不通过。
Access-Control-Request-Method是请求的方法,Access-Control-Allow-Methods是允许的方法
Access-Control-Request-Headers

JSONP

JSONP跨域巧妙的利用了script标签能跨域的特点,实现了json的跨域传输。
随便找了个有callback的网站

1
2
3
4
5
6
<script>
function book(data) {
alert(data.result.bookName);
};
</script>
<script type="text/javascript" src='https://m.zongheng.com/h5/ajax/chapter?bookId=195804&chapterId=4210194_2&callback=book'></script>