zoukankan      html  css  js  c++  java
  • 浏览器同源策略与跨域问题的解决方案

    1、浏览器的同源策略

    同源策略是一个重要的安全策略,它用于限制一个origin的文档或者它加载的脚本如何能与另一个源的资源进行交互。它能帮助阻隔恶意文档,减少可能被攻击的媒介

    1.1.同源的定义

    如果两个 URL 的 protocolport (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源。这个方案也被称为“协议/主机/端口元组”,或者直接是 “元组”。(“元组” 是指一组项目构成的整体,双重/三重/四重/五重/等的通用形式)

    下表给出了与 URLhttps://ims.blibee.com/#/produce/skuProduc的源进行对比的示例:

     

    URL地址是否同源原因备注
    https://abc.efg.com/#/menu/allMenu 同源 只有路径不同是同源的  
    http://abc.efg.com/#/menu/allMenu 不同源 协议不同  
    https://abc.efg.com:8888/#/menu/allMenu 不同源 端口不同  
    http://xyz.efeaef.com/#/sysConfig 不同源 主机,域名均不同  
           

     

     

     

     

     

     

    1.2源的继承和更改

    在页面中通过 about:blank 或 javascript: URL 执行的脚本会继承打开该 URL 的文档的源,因为这些类型的 URLs 没有包含源服务器的相关信息。

    满足某些限制条件的情况下,页面是可以修改它的源。脚本可以将 document.domain 的值设置为其当前域或其当前域的父域。如果将其设置为其当前域的父域,则这个较短的父域将用于后续源检查。

     

    1.3跨源网络访问

    同源策略控制不同源之间的交互,例如在使用XMLHttpRequest 或 <img> 标签时则会受到同源策略的约束。这些交互通常分为三类:

     

    跨域写操作 一般是被允许的例如链接(links),重定向以及表单提交。特定少数的HTTP请求需要添加 preflight
    跨域资源嵌入 一般是被允许(后面会举例说明)
    跨域读操作 一般是不被允许的但常可以通过内嵌资源来巧妙的进行读取访问

     

     

     

     

     

    可嵌入跨域资源的一些示例:

     

    示例类型标签名备注
    JavaScript脚本 <script> 标签嵌入跨域脚本。语法错误信息只能被同源脚本中捕捉到
    样式文件 <link> 由于CSS的松散的语法规则,CSS的跨域需要一个设置正确的 HTTP 头部 Content-Type
    图片文件 <img> 支持的图片格式包括PNG,JPEG,GIF,BMP,SVG,...
    视频文件 <video> 可以跨域访问或者播放视频资源
    音频文件 <audio> 可以跨域访问或者播放音频资源
    插件 <object>、 <embed> 和 <applet> 可以跨域访问插件
    字体 @font-face 一些浏览器允许跨域字体( cross-origin fonts),一些需要同源字体(same-origin fonts)
    框架 <iframe> 可以跨域加载iframe载入的任何资源。站点可以使用 X-Frame-Options 消息头来阻止这种形式的跨域交互

     

     

     

     

     

     

     

     

     

    1.4如何允许和禁止跨域访问

    可以使用 CORS 来允许跨源访问。CORS 是 HTTP 的一部分,它允许服务端来指定哪些主机可以从这个服务端加载资源。

     

    阻止跨域写操作,只要检测请求中的一个不可推测的标记(CSRF token)即可,这个标记被称为 Cross-Site Request Forgery (CSRF) 标记。你必须使用这个标记来阻止页面的跨站读操作。

    阻止资源的跨站读取,需要保证该资源是不可嵌入的。阻止嵌入行为是必须的,因为嵌入资源通常向其暴露信息。

    阻止跨站嵌入,需要确保你的资源不能通过以上列出的可嵌入资源格式使用。浏览器可能不会遵守 Content-Type 头部定义的类型

     

    1.5同源策略限制类型

    类型场景备注
    DOM同源限制

    浏览器中禁止对不同源页面 DOM 进行操作。这里主要场景是 iframe 跨域的情况,

    不同域名的 iframe 是限制互相访问的。

    跨域访问的iframe中的DOM是读不到也无法更改的
    XMLHttpRequest同源限制 浏览器中禁止使用 XHR 对象向不同源的服务器地址发起 HTTP 请求  
    存储同源限制 浏览器中禁止跨域访问cookie、localStorage、sessionStorage、indexedDB等web存储信息

    其中cookie的设置与其他存储略有不同,置 cookie 时,

    可以使用 DomainPathSecure、和 HttpOnly 标记来限定其可访问性

     

     

     

     

     

     

     

    2、解决跨域的几种方式

    解决跨域有以下方法:

     

    序号方法名原理实现方式备注
    1 降域

    同源策略认为域和子域属于不同的域,

    比如以下域名:

    child1.a.com 与 a.com,
    child1.a.com 与 child2.a.com

    通过设置 document.domain='a.com',

    浏览器就会认为它们都是同一个源。

    想要实现以上任意两个页面之间的通信,

    两个页面必须都设置documen.domain='a.com

    • 只能在父域名与子域名之间使用,且将 xxx.child1.a.com域名设置为a.com后,
      不能再设置成child1.a.com
    • 存在安全性问题,当一个站点被攻击后,另一个站点会引起安全漏洞
    • 这种方法只适用于 Cookie 和 iframe 窗口
    2  JSONP跨域

    就是动态创建<script>标签,然后利用<script>的 src 属性

    不受同源策略约束来跨域获取数据

    SONP 由两部分组成:回调函数 和 数据。

    回调函数是用来处理服务器端返回的数据,

    回调函数的名字一般是在请求中指定的。

    而数据就是我们需要获取的数据,也就是服务器端的数据

    • 只支持 GET 请求
    • 由于是从其它域中加载代码执行,因此如果其他域不安全,很可能会在响应中夹带一些恶意代码。
    • 要确定 JSONP 请求是否失败并不容易。
    • 虽然 HTML5 给 script 标签新增了一个 onerror 事件处理程序,但是存在兼容性问题。
    3 window.name跨域

    window 对象有个 name 属性,该属性有个特征:即在一个窗口(window)的生命周期内,

    窗口载入的所有的页面(不管是相同域的页面还是不同域的页面)都是共享一个 window.name 的。

    每个页面对 window.name 都有读写的权限,

     window.name 是持久存在一个窗口载入过的所有页面中的,

    并不会因新页面的载入而进行重置

    只能用于iframe跨域
    4 location.hash跨域 location.hash 方式跨域,是子框架具有修改父框架 src 的 hash 值,通过这个属性进行传递数据 更改 跨域iframe中的hash 值,页面不会刷新,但可以读取到参数 但是传递的数据的字节数是有限的,受到URL的长度限制,不同浏览器中不同
    5 postMessage

    window.postMessage(message,targetOrigin) 方法是 HTML5 新引进的特性,

    可以使用它来向其它的 window 对象发送消息,无论这个 window 对象是属于同源或不同源

    调用 postMessage 方法的 window 对象是指要接收消息的那一个 window 对象,

    该方法的第一个参数 message 为要发送的消息,类型只能为字符串;

    第二个参数 targetOrigin 用来限定接收消息的那个 window 对象所在的域,如果不想限定域,可以使用通配符 *

    需要接收消息的 window 对象,可是通过监听自身的 message 事件来获取传过来的消息,

    消息内容储存在该事件对象的 data 属性中。

    6 WebSocket

    WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。

    该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。

       
    7 设置CORS资源共享

    CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

    它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制

    详细过程可以参考阮一峰老师的文章:

    http://www.ruanyifeng.com/blog/2016/04/cors.html

     
    8 使用服务器代理

    因为http请求在服务器与服务器之间是不存在同源策略的限制。所以在进行跨域AJAX请求是,

    通常进行服务器代理的方式。实际上,大部分公司的业务都是这么做的,最出名的代理服务器就是

    大名鼎鼎的Nginx。

    在前端开发过程中,因为本地调试的前端域名通常是locahost,直接进行AJAZ请求,一般都会跨域,

    前端框架实际上是搭建了本地的Nodejs服务,通过proxy设置,将本地的请求通过服务区转发,

    实现了服务器代理的功能

    htttp请求通过服务转发到实际请求的地址当中,这样就避免了直接访问服务造成的

       

     

     

  • 相关阅读:
    git 远程仓库的使用
    git 以及 工作区 版本库 暂存区
    git repo gerrit 的关系
    【转】c# delegate
    【转】分析.net中的object sender与EventArgs e
    如果plsql连接没问题,但程序中报ORA-12504的错误
    【转】C# String 与 Char[] 数组 相互转换
    【转】C#日期时间格式化
    PLSQL导出语句的查询结果
    oracle取order by的第一条数据
  • 原文地址:https://www.cnblogs.com/liquanjiang/p/12863411.html
Copyright © 2011-2022 走看看