JS篇 同源策略、CORS、XSS、SessionCookie

同源策略:

如何引用: (iFrame指的是iframe DOM节点)
1. 引用iframe的window对象:iFrame.contentWindow
2. 引用iframe的document对象:iFrame.contentDocument,或者:iFrame.contentWindow.document

 

示例:

两个页面,前者页面中嵌入iframe,src指向后者:
1. test.nuomi.com/link1.vm
2. nuomi.com/link2.vm;

 

同源要求:Protocols, domains, and ports均相同
子域名不同的两个站:test.nuomi.com, nuomi.com,如果要通信,必须设置为统一的域名:document.domain=nuomi.com;
即使其中一个已经是域名:nuomi.com,仍然需要明确调用:document.domain=nuomi.com;

 

document.domain设值:
1. 只能是当前域名的suffix,否则报错:Uncaught SecurityError: Failed to set the 'domain' property on 'Document': 'test' is not a suffix of 'test.nuomi.com'.
2. 设值为com也会报错:'com' is a top-level domain.
3. 必须是"."点分隔的后缀,否则报错:'mi.com' is not a suffix of 'test.nuomi.com'

 

不同源时:

1. 外面访问里面window的document属性:iFrame.contentDocument
Chrome报错:  Uncaught SecurityError: ... Protocols, domains, and ports must match.
Firefox报错:   null
IE9报错:      SCRIPT5: 拒绝访问

2. 里面访问外面window的document属性:window.parent.document
Chrome报错:  Uncaught SecurityError: ... Protocols, domains, and ports must match.
Firefox报错:   Permission denied to access property 'document'
IE9报错:    SCRIPT5: 拒绝访问

 

术语:

1. CORS    Cross-Origin-Resource-Sharing. (跨域资源共享)  

2. ACAO    Access-Control-Allow-Origin

 

解决方案:

1. 如果都属于同一个域名,但子域不同时,都设置document.domain;即可相互访问;

2. JSONP通信

// jQuery JSONP
var def = $.ajax({
    url:    "http://nuomi.com/test/request/page/jsonp0.jsp",
    dataType:   "jsonp",
    //jsonp:  "cbNameFlag",
    jsonpCallback:  "cbNameTest"
}).done(function(data, textStatus, jqXHR ){
    console.log("Access done:", arguments, data.info);
}).fail(function( jqXHR, textStatus, errorThrown){
    console.log("Access fail:", arguments);
});

 3. Access-Control-Allow-Origin

  这种方案支持两种:

  1) 简单的请求:

  请求方法不支持Put,Delete

  此时Request header会包含:Origin: http://test.nuomi.com;

  期待Response header包含:Access-Control-Allow-Originhttp://test.nuomi.com

   2) Preflight方式的请求:

  这种方式,代码中虽然请求一次,但是实际会请求两次:第一次发送OPTION方法,询问对方是否支持我方某种请求方式(如:GET,POST)?如果第一次进过允许,那么发送第二次请求;否则第二次不再发送;

  第一次请求:

    Request头包括:  OriginAccess-Control-Request-MethodAccess-Control-Request-Headers(optional),

    Response头包括: Access-Control-Allow-OriginAccess-Control-Allow-MethodsAccess-Control-Allow-Headers

     如图所示:

JS篇 同源策略、CORS、XSS、SessionCookie_第1张图片

  第二次请求:

    直接用代码中的方法发送(PUT、DELETE),然后得到结果;

   从"6. CORS tutorial"转载的流程如下:

JS篇 同源策略、CORS、XSS、SessionCookie_第2张图片

4. postMessage解决跨域问题,支持IE9及以上;

/* 外面页面的script */
function msgHandler(e){
  console.log("Outer message:", e);
}

if(window.addEventListener){
  window.addEventListener("message", msgHandler, false);
}else{
  window.attachEvent("message", msgHandler);
}

// 待加载后发送
$("#iframe1").on("load", function(e){
  console.info("Iframe onLoad:", e);
  $("#iframe1")[0].contentWindow.postMessage("Data from outer, repects 'the structured clone algorithm. '", "*");
});
 1 /* 里面页面的script */
 2 function msgHandler(e){
 3     console.log("Inner message:", e);
 4 }
 5 
 6 if(window.addEventListener){
 7     window.addEventListener("message", msgHandler, false);
 8 }else{
 9     window.attachEvent("message", msgHandler);
10 }
11 window.parent.postMessage("Data from inner to outer.", "*");

 

CORS:

  全称是跨域资源共享(Corss Origin Resource Sharing), 于2014年1月已经成为CORS W3C标准。里面增加了预请求Preflight以支持更广范围的场景。

  常见的头信息包括:

  Request Headers:

  Origin、Access-Control-Request-Method、Access-Control-Request-Headers

  Response Headers:

  1. 允许向该服务器提交请求的URI

  Access-Control-Allow-Origin: | *

  2. 浏览器允许访问的服务器的头信息的白名单

  Access-Control-Expose-Headers: ..., ...

  3. 请求有效期(单位:秒):

  Access-Control-Max-Age:

  4. 允许的请求方法:

  Access-Control-Allow-Methods

  5. 实际的请求中,可以使用的自定义HTTP请求头

  Access-Control-Allow-Headers

  6. 告知客户端,当请求XHR的withCredientials属性是true的时候,响应是否可以被得到。(从而使得下一次请求时,上一次的Cookies可以随着请求发送

  Access-Control-Allow-Credentials

  例子:  withCredential   without credential

  

 

参考资料:

1. Same-origin policy      https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy#Changing_origin

2. document.domain      https://developer.mozilla.org/en-US/docs/Web/API/document.domain

3. HTML