同源策略同源策略是一种重要的安全策略,它限制一个来源的文档或它加载的脚本如何与另一个来源的资源交互。它有助于阻止恶意文档并减少可能的攻击媒介。提交表单不受同源策略的约束。因为不需要回应。同协议、同域名、同端口限制范围:(1)无法读取Cookie、LocalStorage、IndexDB。(2)获取不到DOM。(3)无法发送AJAX请求(有或没有cookie)。规避1.共享cookie两个网页的一级域名相同,二级域名不同。document.domain='example.com';document.cookie="test1=hello";Set-Cookie:key=value;域名=.example.com;path=/2、iframeDOM从完全不同的来源获取两个网页,获取不到dom。两个网页的一级域名相同,二级域名不同。document.domain='example.com';document.getElementById("myIFrame").contentWindow.documentwindow.parent.document.body跨域窗口的通信是针对完全不同的源目前解决跨域的方法有3种窗口通信:1.片段标识符2.window.name3.跨文档通信API(Cross-documentmessaging)window.postMessage1。片段标识符(fragmentidentifier)varsrc=originURL+'#'+data;document.getElementById('myIFrame').src=src;window.onhashchange=checkMessage;parent.location.href=目标+“#”+散列;2.窗口。名称浏览器窗口有一个window.name属性。该属性最大的特点是,无论同源与否,只要前一个网页在同一个窗口设置了该属性,后一个网页就可以读取。这种方式的好处是window.name容量大,可以放很长的字符串;缺点是必须监听子窗口window.name属性的变化,影响网页性能。3.postMessagevarpopup=window.open('http://bbb.com','title');popup.postMessage('HelloWorld!','http://bbb.com');window.opener.postMessage('很高兴见到你','http://aaa.com');window.addEventListener('message',function(e){},false);window.postMessage,传递自定义消息或LocalStorage数据。三、AJAX异步JavaScript和XML。无需重新加载(刷新)整个页面即可快速呈现UI的增量更新。JSONP:http://example.com/ip?callback=fooWebSocket:该协议没有实现同源策略,只要服务器支持,就可以用于跨域通信。CORS:跨域资源共享CORSCORS需要浏览器和服务端都支持。目前主流浏览器都支持cors。整个CORS通信过程由浏览器自动完成,无需用户参与。对于开发者来说,CORS通信和同源AJAX通信没有区别,代码完全一样。浏览器一旦发现AJAX请求是跨域的,就会自动添加一些额外的header信息,有时会有额外的请求,但是用户是感觉不到的。因此,实现CORS通信的关键是服务器。只要服务端实现了CORS接口,就可以实现跨域通信。简单请求(simplerequest)(1)请求方式为以下三种方式之一:HEADGETPOST(2)HTTP头信息不超过以下字段:AcceptAccept-LanguageContent-LanguageLast-Event-IDContent-Type:限于三个Valueapplication/x-www-form-urlencoded,multipart/form-data,text/plain基本流程对于简单请求,浏览器直接发送CORS请求。具体的,在头信息中增加Origin字段。如果Origin-指定的域名不在允许范围内,服务器将返回一个正常的HTTP响应。当浏览器收到这个响应,发现这个响应的头信息中不包含Access-Control-Allow-Origin字段时,就知道是错误的,从而抛出错误,这个错误被onerror的回调函数捕获XMLHttpRequest。此时HTTP响应的状态码可能是200。-在允许的范围内,服务器返回的响应会多出几个头信息字段。Access-Control-Allow-Origin:该字段必填,取值可以是请求时Origin字段的值,也可以是*,表示接受任何域名请求。Access-Control-Allow-Credentials:该字段可选,取值类型为Boolean,表示是否允许发送cookie。默认情况下,cookie不包含在CORS请求中。Access-Control-Expose-Headers:该字段是可选的。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能获取6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果要获取其他字段,必须在Access-Control-Expose-Headers中指定。withCredentials属性,携带cookie默认情况下,CORS请求默认不发送cookie和Http认证信息。如果要向服务器发送cookie,则必须首先指定Access-Control-Allow-Credentials字段。Access-Control-Allow-Credentials=true另一方面,需要在AJAX请求中打开withCredentials属性。请求携带cookiexhr.withCredentials=true;如果该属性设置为false,即使服务器同意发送cookie,浏览器也不会发送。或者,服务器要求设置cookie,浏览器不会处理它们。如果省略withCredentials设置,一些浏览器仍然会一起发送cookie。此时,可以显式关闭withCredentials。需要注意的是,如果要发送cookies,Access-Control-Allow-Origin不能设置为星号,必须指定明确的域名,与请求的网页一致。同时,cookie仍然遵循同源策略。只会上传服务器域名设置的cookies,不会上传其他域名的cookies,并且(跨域)原网页代码中的document.cookie无法读取cookies。非简单请求(not-so-simplerequest)是对服务端有特殊要求的请求,比如请求方法是PUT或者DELETE,或者Content-Type字段的类型是application/json。对于不是简单请求的CORS请求,在正式通信之前会添加一个HTTP查询请求,称为“预检”请求(preflight)。浏览器首先询问服务器当前网页的域名是否在服务器的权限列表中,可以使用哪些HTTP动词和头信息字段。“预检”请求使用的请求方式为OPTIONS,通过后浏览器会发送正式的XMLHttpRequest请求,否则会报错。有关更多详细信息,请参阅浏览器同源策略以及如何规避它。一旦服务器通过了“pre-check”请求,浏览器每次正常的CORS请求都会和一个简单的请求一样,都会有一个Origin头字段。服务器的响应也将有一个Access-Control-Allow-Origin标头字段。预检响应标头Access-Control-Allow-Origin:必须包含在每个响应中。Access-Control-Allow-Methods:标头字段用于预检请求的响应。它指定实际请求允许的HTTP方法。Access-Control-Allow-Headers:如果浏览器请求包含Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,用于预检请求的响应,表示实际请求中允许的头字段,不限于浏览器在“预检”中请求的字段。Access-Control-Max-Age:该字段可选,用于指定本次预检请求的有效期,单位为秒。在上面的结果中,有效期为20天(1728000秒),也就是说response允许缓存1728000秒(20天),在此期间,不需要再发送preflight请求。Access-Control-Allow-Credentials:与简单请求相同。与JSONP的比较CORS与JSONP的用途相同,但比JSONP更强大。JSONP只支持GET请求,而CORS支持所有类型的HTTP请求。JSONP的优点是支持旧浏览器,可以向不支持CORS的网站请求数据。参考:阮一峰老师【BrowserSameOriginPolicyandHowtoAvoidIt】MDN【BrowserSameOriginPolicy】Access-Control-Allow-Headers等基础知识
