同源策略(The same-origin policy)

这是浏览器的一个基本却又非常重要的安全策略,浏览器会限制对异源(异域)(我们常称之为别人家的站点)的资源操作。打个比方,你不会让老王来你家,也不允许他在你家墙上打个洞,装个监控啥的。通过这个比喻你就知道同源策略的重要性了。

同源策略主要针对脚本(script)的行为进行限制,而<script>,<link>,<img>,<iframe>,<object>等带有src属性的dom元素一般不受影响,这也很好理解,你可以禁止老王进你家,但是无法限制他在自己家装个雷达对你家进行监控。因此,在没有得到授权的情况下,用javascript脚本操作异域的资源,那是不允许的。科学的说法应该是:浏览器允许发起请求,但如果响应中没有包含对方的许可的话,浏览器就会屏蔽响应结果,不给你用。经常会抛出这样的异常: XMLHttpRequest cannot load http://www.othersite.com/. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://www.mysite.com' is therefore not allowed access.

源(Origin)

唠叨了半天异源(异域),科学的解释一下什么是源(Origin)

公式:Origin = [protocol]://[domain]:[port]

Origin是你的页面所在的位置。例如我有个站点www.mysite.com,那么它的就是http://www.mysite.com:80,其中[protocol]的缺省值是http[port]的缺省值是80

不管我的站点在哪个页面www.mysite.com/p/1.html,只要[protocol],[domain],[port]三者相同则视为同源,或者叫同域,通常称之为同域,因为我们通常都是叫别人的小名二狗子,而不会称呼其大名犬次郎

更多示例:

URL Origin
http://www.mysite.com/p/1.html http://www.mysite.com
https://wwww.mysite.com/p/1.html https://www.mysite.com
http://app.mysite.com/p/1.thml http://app.mysite.com
http://www.mysite.net/p/1.html http://www.mysite.net
http://www.mysite.com:9000/p/1.html http:www.mysite.com:9000
http://www.mysite.com/news/fresh.html http://www.mysite.com

解决访问跨域资源的问题

虽然是安全了,但是如果想从我的www.mysite.com去我的分站son.mysite.com获取点东西也会被同源策略禁止,这就不是我们想要的了,那怎么办呢?可以利用<script>等不受同源策略限制的dom元素绕过去,这种方式称之为jsonp,这是很多年前就提出来的方法,很巧妙不过很繁琐,渐渐地不怎么再使用了,有兴趣的自行google

还有现代化的解决方案:CORS(Cross-Origin Resource Sharing)。还记得同源策略的规定吗?通过屏蔽响应结果的方式保证信息安全,也就是说浏览器并没有阻止发起跨域请求。浏览器如果在跨域请求的响应(Http Response Headers)中发现了对方的许可就会认为是安全的。这套标准称之为CORS。

这套标准规定一系列的Http Headers,让服务器申明哪些资源是可以被谁访问,浏览器通过解析响应头部就能知道是否得到了许可。

举两个简单的?栗子说明这一系列的Http Headers:

  1. www.mysite.com中有如下脚本,要去访问www.othersite.com的资源。
<script>
var request = new XMLHttpRequest();
var url = 'www.othersite.com/post/001/';function callOtherDomain() {if(request) {    request.open('GET', url, true);request.onreadystatechange = handler;request.send(); }
}
</script>

通过浏览器的控制台,查看到该请求,请求和响应报文的重要内容如下:

请求报文

GET /post/001 HTTP/1.1
Host: www.othersite.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Referer: www.mysite.com
Origin: http://www.mysite.com

响应报文

HTTP/1.1 200 OK
Date: Sat, 04 Mar 2017 14:23:53 GMT
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked

这是一个简单的Get请求,在请求报文中有一个值得注意的Origin,这个属性就表示了当前所处的,Origin是由浏览器自动控制的,不允许用户干预。如果同源策略判定请求是跨域请求,那么就会自动把Origin加入请求头部中。

在响应报文中,注意Access-Control-Allow-Origin属性,如果对方允许你跨域访问,那么它会在响应中加入你的请求头部中的Origin,此处的响应报文中的*表示允许任何请求的跨域访问。

  1. https://www.mysite.com要去修改https://posts.mysite.com中的一篇文章。
var request = new XMLHttpRequest();
var url = 'posts.mysite.com/?pid=1024';
var body = 'new post';function callOtherDomain(){if(request){request.open('PUT', url, true);request.setRequestHeader('userid', 'keke');request.onreadystatechange = handler;request.send(body); }
}

这次是发送了PUT类型的请求,要去修改pid=1024的文章,同时还携带了我的身份信息userid=keke在请求头部中。继续在浏览器的控制台中观察请求信息,发现有两次请求,第一个如下:

OPTIONS /?pid=1024
Host: https://posts.mysite.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
Origin: https://www.mysite.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: useridHTTP/1.1 200 OK
Date: Sat, 04 Mar 2017 14:35:39 GMT
Access-Control-Allow-Origin: https://www.mysite.com
Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT
Access-Control-Allow-Headers: userid
Access-Control-Max-Age: 1728000
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

这是因为这次发送的不是简单请求,CORS规范要求先发个预检请求(Preflight),一般会采用OPTIONS类型,该请求不包含请求体,会携带一些用于探测的信息,除了Origin,还有

* `Access-Control-Request-Method`
* `Access-Control-Request-Headers`

前者用来携带真正的请求的类型,后者携带真实请求自定义的头。

在响应报文中还有Access-Control-Allow-Methods: POST, GET, OPTIONS, PUT表示对方许可的请求类型。

对方会根据预检请求中的信息判断是否可以接受真正的请求,如果预检请求通过了,浏览器才会发起真正的请求。

PUT /?pid=1024/ HTTP/1.1
Host: https://posts.mysite.com
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Connection: keep-alive
userid: keke
Content-Type: text/xml; charset=UTF-8
Referer: https://www.mysite.com
Content-Length: 8
Origin: https://www.mysite.com
Pragma: no-cache
Cache-Control: no-cache
……HTTP/1.1 200 OK
Date: Sat, 04 Mar 2017 14:35:39 GMT
Access-Control-Allow-Origin: https://www.mysite.com
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
……

响应报文报文头部中带有Access-Control-Allow-Origin: https://www.mysite.com,表示对方同意
https://www.mysite.com的请求,浏览器就不会屏蔽响应结果。

上述栗子中,提到了CORS规定了对于不简单的请求类型,要先发一个预检请求(Preflight),那么简单与否的判定条件是什么呢?在如下范围内的请求都是被视为简单请求

  1. 请求类型的范围限制:GET,HEAD,POST
  2. 自定义的请求头部限制范围:Accept,Accept-Language,Content-Language
  3. 媒体类型(Content-Type)的限制范围的:application/x-www-form-urlencoded,multipart/form-data,text/plain

除来上述栗子中提到的几个头部,还有哪些呢?如下明细:

HTTP请求头部

  1. Origin: 表示发送请求者的源(域),浏览器控制的。
  2. Access-Control-Request-Method: 这是预检请求(Preflight)中表示真实请求的请求方式。
  3. Access-Control-Request-Headers: 这是预检请求(Preflight)中表示真实请求的自定义的头部,可以有多个(Access-Control-Request-Headers: userid, pwd, location:表示真实请求会携带3个自定义头部(userid,pwd,location))。

HTTP响应头部

  1. Access-Control-Allow-Origin: <origin> | *: origin参数表示对方允许访问的URI.对于一个不带有credentials的请求,可以指定为'*',表示允许来自所有域的请求。
  2. Access-Control-Expose-Headers: X-My-Custom-Header, X-Another-Custom-Header: 设置允许的请求头部。
  3. Access-Control-Max-Age: <delta-seconds>: 这个头告诉我们这次预检请求的结果的有效期是多久,delta-seconds 参数表示,允许这个预检请求的参数缓存的秒数,在此期间,不用发出另一条预检请求
  4. Access-Control-Allow-Credentials: true | false: 告知客户端,当请求的credientials属性是true的时候,响应是否可以被得到.当它作为预检请求的响应的一部分时,它用来告知实际的请求是否使用了credentials.注意,简单的GET请求不会预检,所以如果一个请求是为了得到一个带有credentials的资源,而响应里又没有Access-Control-Allow-Credentials头信息,那么说明这个响应被忽略了。
  5. Access-Control-Allow-Methods: <method>[, <method>]*: 这个响应头信息在客户端发出预检请求的时候会被返回,表示被允许的请求方式。
  6. Access-Control-Allow-Headers:<field-name>[, <field-name>]*: 也是在响应预检请求的时候使用。用来指明在实际的请求中,可以使用哪些自定义HTTP请求头。

对于Access-Control-Allow-Credentials这个头部只会出现在请求头部中包含了凭证(HttpCookie)信息。一般而言,对于跨站请求,浏览器是不会发送凭证信息的。但如果将XMLHttpRequest的一个特殊标志位设置为true,浏览器就将允许该请求的发送。

var invocation = new XMLHttpRequest();
var url = 'http://www.othersite.com';function callOtherDomain(){if(invocation) {invocation.open('GET', url, true);invocation.withCredentials = true;invocation.onreadystatechange = handler;invocation.send(); }

再例如使用jQuery发起ajax请求时:

$.ajax({//...xhrFields: {withCredentials: true},//...
});

针对脚本(script)的跨域操作是安全了,可是如果通过<iframe>这种dom元素来嵌入资源的话,同源策略就无法保护我们了。

针对<iframe>的安全策略

我们肯定不希望自己的页面被不法分子用<iframe src="www.mysite.com"></frame>等方式嵌入,然后被利用。浏览器们早已考虑到这个漏洞,并提出了解决方案。类似于CORS标准,解析响应头部中的X-Frame-Options,用这个头部信息来表达是否可以被对方嵌入。

X-Frame-Options有三种值:

X-Frame-Options: DENY
X-Frame-Options: SAMEORIGIN
X-Frame-Options: ALLOW-FROM https://www.othersite.com/
  1. DENY: 无论请求者是谁,都不允许嵌入。
  2. SAMEORIGIN: 只有同源(origin)的页面才可以嵌入。
  3. ALLO-From https://www.othersite.com/: 只有https://www.othersite.com/才可以嵌入咱们的页面。

例如,www.othersite.com要用如下代码嵌入我的页面www.mysite.com

...
<iframe src="www.mysite.com"></iframe>
...

我给www.mysite.com的响应头部中加入X-Frame-Options: SAMEORIGIN,浏览器会屏蔽响应结果,并报错Refused to display 'http://www.mysite.com/' in a frame because it set 'X-Frame-Options' to 'SAMEORIGIN'.

这些都是基本的网络安全规范,但是其重要性却不可忽略。面对红果果的互联网,时刻不能放松。

转载于:https://www.cnblogs.com/kexxxfeng/p/6505380.html

毁人不倦-令人困惑的浏览器安全策略:同源策略相关推荐

  1. 【每天学习一点新知识】浏览器的同源策略

    目录 同源的定义 同源策略的限制 规避同源策略 document.domain属性 跨域资源共享(CORS) 跨文档通信 JSONP WebSocket Nginx反向代理         浏览器默认 ...

  2. 美多商城后台管理之登录、浏览器的同源策略

    登录 后台管理中我们首先需要完成登录功能,我们可以通过改写美多表单登录来完成相应的功能. 在后台登录中,由于我们前端服务和后端服务的域名不一样,所以我们首先解决跨域问题. 登后的状态保持我们采用jwt ...

  3. 浏览器的同源策略与跨域问题的解决方案

    浏览器的同源策略与跨域问题的解决方案 参考文章: (1)浏览器的同源策略与跨域问题的解决方案 (2)https://www.cnblogs.com/yanggb/p/10735763.html 备忘一 ...

  4. 什么是浏览器的同源策略?

    有时在开发中我们会遇到跨域的问题,众所周知,跨域是由浏览器的同源策略引起的,那么什么是浏览器的同源策略呢? 同源策略,是浏览器对javascript施加的安全限制.所谓同源是指,域名,协议,端口均相同 ...

  5. 浏览器的同源策略是什么,没有同源策略会怎么样?

    同源策略 同源策略由Netscape提出的一个著名的安全策略. 现在所有可以支持JavaScript的浏览器都会使用这一策略. 同源 同源即 同协议,端口,域名 同源策略的限制 不能获取不同源的coo ...

  6. 浏览器的同源策略与跨域

    本文所有案例在本地址都可找到:https://github.com/dancingZhou/sameOrigin/tree/dev 什么是同源策略 两个页面地址中的协议.域名和端口号一致,则表示同源. ...

  7. 浏览器的同源策略及跨域解决方案

    同源策略 一个源的定义 如果两个页面的协议,端口(如果有指定)和域名都相同,则两个页面具有相同的源. 举个例子: 下表给出了相对http://a.xyz.com/dir/page.html同源检测的示 ...

  8. 浏览器的同源策略和跨域请求_学习版

    目录 同源策略 : 跨域请求 : 跨域请求的常见解决方案 : 1. jsonp 2. cors(跨域资源共享) 3. proxy(代理) 同源策略 : 什么是同源策略 ? + 同源策略是  浏览器  ...

  9. 同源策略——浏览器安全卫士

    对于软件开发人员来说,理解同源策略.能够非常好地攻克了一个痛点. 不同域名下的资源读写 ! 古代的楚河汉界明白地规定了两方的活动界限.假设没有这些界限,天下必将大乱.相同,在我们的浏览器,也有着一些界 ...

  10. gorilla websocket无法跨域_聊聊浏览器同源策略与跨域方案详解

    开发出高性能的 Web 应用固然重要,但安全问题也不容小觑.本文我们继续以 HTTP 为线索,展开来讲一讲浏览器安全相关的同源策略. 浏览器的同源策略(Same Origin Policy) 源(Or ...

最新文章

  1. FEAST:快速准确的微生物来源追溯工具
  2. 2018-2019-1 20189204《Linux内核原理与分析》第三周作业
  3. 《研磨设计模式》chap22 装饰模式Decorator(4)AOP+总结
  4. 运行 YunYang1994/tensorflow-yolov3 所遇到的一些问题记录
  5. 【STM32】FreeRTOS移植
  6. leetcode654. 最大二叉树
  7. lz0-007 读书笔记03
  8. original_keras_version = f.attrs[‘keras_version‘].decode(‘utf8‘)AttributeError: ‘str‘ object has no
  9. 瀑布流布局的实现方式
  10. cocos2d-x CCArray用法 遍历和删除元素
  11. android simpliadapter的两种用法
  12. chapter10--进程和计划任务管理
  13. linux抓肉鸡入侵详细教程,Linux XOR.DDoS入侵排查步骤 | 聂扬帆博客
  14. 24种不同的ITF条形码字体版本的条形码控件Interleaved 2 of 5 Barcode Font Advantage Package...
  15. OneNote PC端同步时遇到0×80004005
  16. C#调用Outlook发送邮件
  17. dds:publish
  18. NRF24L01使用
  19. 2022年黑五软件促销
  20. SWR:最具潜力的 React Hooks 数据请求库

热门文章

  1. csdn博客更换皮肤
  2. 2021计算机一级等级考试考前冲刺模拟试题及答案(WPS Office)
  3. 2021年起重机司机(限桥式起重机)考试题库及起重机司机(限桥式起重机)考试试卷
  4. Unity TimeLine实用功能讲解
  5. 第四章 SQL语法分类
  6. 《C语言程序设计》第4版 何钦铭、颜晖主编 课后习题答案 第4章 课后习题
  7. The chain rule(链式法则)
  8. openwrt 添加usb网卡_树莓派安装OpenWrt教程
  9. 微端服务器添加文件,微端服务器配置
  10. “Google Play In-app Billing API version is less than 3”的解决方法