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


    目录

    同源的定义 

    同源策略的限制

    规避同源策略

    document.domain属性

    跨域资源共享(CORS)

    跨文档通信

    JSONP

    WebSocket

    Nginx反向代理


            浏览器默认两个相同的源之间是可以相互访问资源和操作 DOM 的。两个不同的源之间若想要相互访问资源或者操作DOM,那么会有⼀套基础的安全策略的制约,我们把这称为 同源策略   

            同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介。它的存在可以保护用户隐私信息,防止身份伪造等(读取Cookie)。

    同源的定义 

    一个域名地址由 协议、域名、端口、请求资源地址 等部分组成。

    如果两个 URL 的协议、域名和端口都相同,我们就称这两个 URL 同源即便两个不同的域名指向同一个 ip 地址,也非同源。

    下表给出了与 URL http://store.company.com/dir/page.html 的源进行对比的示例: 

    URL结论原因
    http://store.company.com/dir2/other.html同源只有路径不同
    http://store.company.com/dir/inner/another.html同源只有路径不同
    https://store.company.com/secure.html不同源协议不同
    http://store.company.com:81/dir/etc.html不同源端口不同 ( http:// 默认端口是 80)
    http://news.company.com/dir/other.html不同源主机不同

    同源策略的限制

    浏览器的同源策略目的是为了保护用户的信息安全,为了防止恶意网站窃取用户在浏览器上的数据,如果不是同源的站点,将不能进行如下操作 :

    • Cookie、LocalStorage 和 IndexDB 无法读写

            用户登录某个站点,站点后端服务器验证账号密码正确之后,会返回Cookie、Token 或者是用户名和密码给客户端浏览器,浏览器会将这些个人数据保存到Cookie、Session Storage、Local Storage、Cache、Indexed DB其中的一个(具体怎么保存,取决网站开发人员),如果浏览器没有同源策略,当用户访问恶意网站时,恶意网站就可以通过脚本获取用户的数据,这是极其不安全的行为。

            所以在不是同源的情况下,不能读写其他站点设置的Cookie、Session Storage、Local Storage、Cache、Indexed DB。

    • DOM 和 Js对象无法获得

            DOM 是 Document Object Model(文档对象模型)的缩写。

            来自一个源的js只能读写自己源的DOM树不能读取其他源的DOM树。

    • AJAX请求不能发送

            Ajax 全称“Asynchronous JavaScript and XML”,译为“异步 JavaScript 和 XML”。通过 Ajax 可以异步从服务器请求数据并将数据更新到网页中,整个过程不需要重载(刷新)整个网页,可以将网页的内容更快的呈现给用户。

            一般而言来自一个源的js只能向自己源的接口发送请求,不能向其他源的接口发送请求。当然其实本质是,一方面浏览器发现一个源的js向其他源的接口发送请求时会自动带上Origin头标识来自的源,让服务器能通过Origin判断要不要向应;另一方面,浏览器在接收到响应后如果没有发现Access-Control-Allow-Origin允许发送请求的域进行请求那也不允许解析。

    规避同源策略

    在某些情况下同源策略太严格了,给拥有多个子域的大型网站带来问题。下面就是解决这种问题的技术:

    document.domain属性

            如果两个window或者frames包含的脚本可以把domain设置成一样的值,那么就可以规避同源策略,每个window之间可以互相沟通。例如,orders.example.com下页面的脚本和catalog.example.com下页面的脚本可以设置他们的document.domain属性为example.com,从而让这两个站点下面的文档看起来像在同源下,然后就可以让每个文档读取另一个文档的属性。这种方式也不是一直都有用,因为端口号是在内部保存的,有可能被保存成null。换句话说,example.com的端口号80,在我们更新document.domain属性的时候可能会变成null。

    跨域资源共享(CORS)

            这种方式使用了一个新的Origin请求头和一个新的Access-Control-Allow-Origin响应头扩展了HTTP。允许服务端设置Access-Control-Allow-Origin头标识哪些站点可以请求文件,或者设置Access-Control-Allow-Origin头为"*",允许任意站点访问文件。只要浏览器检测到响应头带上了CORS,并且允许的源包括了本网站,那么就不会拦截请求响应。浏览器,例如Firefox3.5,Safari4,IE10使用这个头允许跨域HTTP请求。

            只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。但是,后端服务器如果配置Access-Control-Allow-Origin: *,不管withCredentials有没有设置,cookie也带不过去。

    跨文档通信

            这种方式允许一个页面的脚本发送文本信息到另一个页面的脚本中,不管脚本是否跨域。在一个window对象上调用postMessage()会异步的触发window上的onmessage事件,然后触发定义好的事件处理方法。一个页面上的脚本仍然不能直接访问另外一个页面上的方法或者变量,但是他们可以安全的通过消息传递技术交流。

    JSONP

            JOSNP允许页面接受另一个域的JSON数据,通过在页面增加一个可以从其它域加载带有回调的JSON响应的