zoukankan      html  css  js  c++  java
  • JS系列

     

    同源策略:

    浏览器中有个安全机制,就是同源策略,下面介绍同源策略。同源是指同协议同域名同端口,必须三同,缺一不可。

     

     

    限制范围:

    (1) Cookie、LocalStorage 和 IndexDB 无法读取。

    (2) DOM 无法获得。

    (3) AJAX 请求不能发送。

    避免方案:

    1. 设置docnment.domain

    两个网页一级域名相同,二级域名不同,浏览器允许通过设置document.domain共享 Cookie。

    举例:

    A网页是http://w1.example.com/a.html; B网页是http://w2.example.com/b.html

    设置相同的document.domain,两个网页就可以共享Cookie。document.domain = 'example.com';

     

    iframe上使用:

    实现原理:两个页面都通过js强制设置document.domain为基础主域,就实现了同域。

     

    2. location.hash的iframe跨域

    实现原理:

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

     

    A --> B:

    A页面,有个iframe的B页面,A页面通过选择器获取到B的dom节点,在B的src上添加哈希值;

    B页面通过监听哈希值的变化,获取到A页面传递的数据;

     

    B --> C:

    B页面有个iframe的C页面,地址和A页面同源;

    B页面通过选择器获取到C的dom节点,在C的src上添加哈希值;

    C页面通过监听哈希值的变化,获取到B页面传递的数据;

    C页面和A页面同源,所以能获取A页面的window对象(window.parent.parent),通过传参数调用A页面的方法,间接达到B与A通讯;

     

     

    3.window.name的iframe跨域

    浏览器窗口有window.name属性。这个属性的最大特点是,无论是否同源,只要在同一个窗口里,前一个网页设置了这个属性,后一个网页可以读取它。

    1. 父窗口先打开一个子窗口,载入一个不同源的网页,该网页将信息写入window.name属性。window.name = data;

    2. 接着,子窗口跳回一个与主窗口同域的网址。location = 'http://parent.url.com/xxx.html';

    3. 然后,主窗口就可以读取子窗口的window.name了。var data = document.getElementById('myFrame').contentWindow.name;

    这种方法的优点是,window.name容量很大,可以放置非常长的字符串;缺点是必须监听子窗口window.name属性的变化,影响网页性能。

     

    4.postMessage跨域(跨文本档、多窗口、跨域消息传递)

    HTML5引入了一个全新的API:跨文档通信 API(Cross-document messaging)。这个API为window对象新增了一个window.postMessage方法,允许跨窗口通信,不论这两个窗口是否同源。

     

    语法:otherWindow.postMessage(message, targetOrigin, [transfer]);

    第一个参数是具体的信息内容,

    第二个参数是接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。

     

     

    父向子发信息:子页面window对象.postMessage(参数, 子页面url)

    var popup = window.open('http://bbb.com', 'title');

    popup.postMessage('Hello World!', 'http://bbb.com');

     

    子向父发信息:父页面window对象.postMessage(参数, 父页面url)

    window.opener.postMessage('Nice to see you', 'http://aaa.com');

     

    父子窗口通过message事件获取信息

    window.addEventListener('message', function(e) {console.log(e.data);},false);

    message事件的事件对象event,提供以下三个属性。

      • event.source:发送消息的窗口
      • event.origin: 消息发向的网址
      • event.data: 消息内容

     

    下面是iframe通过postMessage进行跨域:

     

    5.JSONP

    同源政策规定,AJAX请求只能发给同源的网址,否则就报错。除了架设服务器代理,jsonp规避这个限制。

    优点:jsonp是服务器与客户端跨源通信的常用方法。简单适用,老式浏览器全部支持,服务器改造非常小。

    它的基本思想是,使用<script>标签可以跨域的特点实现,具体步骤如下:

    1. 网页动态插入<script>元素,由它向跨源网址发出请求,请求的查询字符串有一个callback参数,指定回调函数的名字。

    2. 服务器返回 script 标签的内容,内容就是调用指定的回调函数,并且将返回数据以参数的显示传递;

     

    6.CORS

    CORS需要浏览器和服务器同时支持。目前所有浏览器都支持该功能,IE浏览器不能低于IE10;

    浏览器将CORS请求分成两类:简单请求(simple request)和非简单请求(not-so-simple request)

    整个通信过程,都是浏览器自动完成。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。

    浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

     

    简单请求:

    同时满足以下两大条件,就属于简单请求

    1. 请求方法是以下三种方法之一:HEAD、GET、POST

    2. HTTP的头信息不超出以下几种字段:Accept、Accept-Language、Content-Language、Last-Event-ID、Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

     

    基本流程:

    1.浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段;Origin字段说明本次请求来自哪个源(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求。

    2.如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现回应的头信息没有包含Access-Control-Allow-Origin字段,抛出一个错误,被XMLHttpRequestonerror回调函数捕获(注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200)

    3.在指定范围,服务器返回的响应,会多出几个头信息字段:

    1. Access-Control-Allow-Origin: http://api.bob.com(请求时Origin字段的值或者*,*表示接受任意域名的请求)

    2. Access-Control-Allow-Credentials: true(布尔值,表示是否允许发送Cookie;默认不发送false; 同时开发者必须在AJAX请求中打开withCredentials属性 xhr.withCredentials = true

    3. Access-Control-Expose-Headers: FooBar (XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-ControlContent-LanguageContent-TypeExpiresLast-ModifiedPragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值)

     

    非简单请求:

    对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是application/json;

     

    基本流程:

    1.会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求;浏览器先询问服务器,当前域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错;("预检"请求用的请求方法是OPTIONS

    2.

    待续。。。。

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

     

     

     

     

     

  • 相关阅读:
    重新想象 Windows 8 Store Apps (15) 控件 UI: 字体继承, Style, ControlTemplate, SystemResource, VisualState, VisualStateManager
    重新想象 Windows 8 Store Apps (12) 控件之 GridView 特性: 拖动项, 项尺寸可变, 分组显示
    返璞归真 asp.net mvc (10) asp.net mvc 4.0 新特性之 Web API
    与众不同 windows phone (29) Communication(通信)之与 OData 服务通信
    与众不同 windows phone (33) Communication(通信)之源特定组播 SSM(Source Specific Multicast)
    与众不同 windows phone (27) Feature(特性)之搜索的可扩展性, 程序的生命周期和页面的生命周期, 页面导航, 系统状态栏
    与众不同 windows phone (30) Communication(通信)之基于 Socket TCP 开发一个多人聊天室
    返璞归真 asp.net mvc (12) asp.net mvc 4.0 新特性之移动特性
    重新想象 Windows 8 Store Apps (2) 控件之按钮控件: Button, HyperlinkButton, RepeatButton, ToggleButton, RadioButton, CheckBox, ToggleSwitch
    重新想象 Windows 8 Store Apps (10) 控件之 ScrollViewer 特性: Chaining, Rail, Inertia, Snap, Zoom
  • 原文地址:https://www.cnblogs.com/vs1435/p/6558525.html
Copyright © 2011-2022 走看看