[Geek] then those issues coquettish cross-domain operation

Foreword

Now cross-origin resource sharing (Cross-Origin Resource Sharing, hereinafter referred to as CORS) has been very popular, do not count IE8 standards compliant (XDomainRequest), the major browsers already support basic, years ago, to separate the front and rear end, iframe and interaction Cross-domain-party plug-in developers headache is the era has passed, but then to do anything to cross-domain flair operation is still worth learning.
This article is not from a practical point of view to consider these cross-domain means old age, but is more interested in elaborate theory, Reflections on the browser and security caused, because the core is actually all kinds of cross-domain attacks.
It limited personal capacity, welcomed the large cattle discuss, criticism.

Same Origin Policy

In 1995, the same-origin policy introduced by Netscape browser. Currently, all browsers have implemented this security policy.
The core is to ensure that between files (resources) provided by different sources independent of each other. In other words, only when the script is to provide different files from the same domain, port, HTTP protocol, it is not particularly limited. Special restrictions can be subdivided into two areas:

  • Object Access restrictions: mainly in the iframe, if his son source page is different, you can not access each other's DOM methods and properties (including Cookie, LocalStorage and IndexDB etc.). Different sources will throw an exception.
  • Network access restrictions: mainly in the AJAX request, if the request is initiated by the source and target different from the current page, the browser will launch a cross-site request limit, or block requests returned.

What is homologous to a table read?

origin(URL) result reason
http://example.com success Protocol, domain name and port number 80 are the same
http://example.com:8080 fail Different port
https://example.com fail Different protocols
http://sub.example.com fail Different domain

As to why this is a security policy?
This is necessary to mention cookie-session mechanism, well known HTTP is a stateless protocol, and how the server knows the user's login status? Traditionally cookie-session is the use of this mechanism, that is, the server generates a session identifier for each visitor, and the session identifier will be returned in the response header contains the server, the browser resolves to set-cookie response header put the string to a local session identifier stored in the cookie, each request using a cookie band characteristics are the same domain, the server is able to know the current user login status.
So if the browser sends a request to let different sources, it will cause great danger. For example, a user logs on the bank's Web site A, that is to say A station has left a cookie in your browser, this time users have access to the B station, if they can initiate requests A station on page B station, the station is equivalent to B you can impersonate a user pleases the A station.
Thus, the "same origin policy" is required, otherwise the cookie can be shared, the Internet, have no security to speak of.

Cross-domain scheme

Origin policy proposed by age or traditional MVC framework (jsp, asp) popular, then the server to render the page by filling completed most of the content is relatively simple, the developers will not maintain a separate API project, so in fact Cross-domain demand is relatively small.
Front and rear end of the new era and the rise of third-party JSSDK of separation, we began to find that although this strategy greatly improves the security of the browser, but sometimes very convenient and reasonable use is also affected. such as:

  1. Independent API project management in order to facilitate the deployment of the use of an independent domain name;
  2. Local front-end developers need to use remote debugging of API;
  3. Third-party developers of embedded JSSDK need to use someone else's page;
  4. Common platform of open API.

Ever since, the standards of the era did not cross-domain solutions on how to solve these problems would have been put forward, contending indeed, many of them stunning Sao operations, such geek spirit is still worthy of our admiration and learning.

JSON-P

JSON-P are all kinds of cross-domain solutions in a high popularity, it is now also being used in some older browsers compatible to the environment, the famous jQuery also encapsulates its methods. Do not see the name to know justice, in the name of P is padding "is filled with" mean, this is not the method used in the communication process in general json, but comes with filling function of JavaScript scripts .
How to understand "that comes with filling function of the JavaScript script", perhaps a look at the following example is relatively simple, if a js file and wrote the introduction, then there will be data objects globally, that the use of the script and introduced js parsing can be used to transfer data , if js script into the run command function would not be called a global function. This is the core idea of JSON-P method, which is populated with data global functions.

var data = {
  a: 1,
  b: 2
}
[PS] <script> label is not the same origin policy restrictions, but can only be initiated get request.

Principles and procedures

  1. First defined the callback function, the function is introduced js script to be called;
  2. New <script>label, the label insert page browser will initiate get request;
  3. The server returned upon request js script, which calls the callback function.

jsonp flow chart

// 定义回调函数
function getTheAnimal(data){
    var myAnimal = data.animal;
}
// 新建标签
var script = document.createElement("script");
script.type = "text/javascript";
// 常用的在url参数部分跟服务器约定号回调函数名
script.src = "http://demo.com/animal.json?callback=getTheAnimal";
document.getElementByTagName('head')[0].appendChild(script);

to sum up

advantage:

  • Simple, readily available tool libraries (jQuery) support;
  • Elder support level browser (IE8-).

Disadvantages:

  • Only the GET method;
  • Subject to a maximum length of 2083 browser URL character limit;
  • Can not debug, server errors can not be detected by specific reasons;
  • There are security risks of CSRF;
  • Can only be asynchronous, synchronous not blocked;
  • Require special interface support, not REST-based API specification.

Proxy subdomains

This method is actually using the browser allows the pages in an iframe as long as it is under the same parent page with the first-level domain names can be modified parent page and calling features. You might doubt, speak the same origin policy is very clear in the table above different second-level domain is considered different sources, this not a contradiction?
In fact, this is not contradictory, if indeed the normal operation will be limited to the same origin policy, but the browser is document.domainallowed to change the original value of the site will host part of the suffix . This means, parked in sub.example.com page can be its source to example.com, but does not bring it to alt.example.com or google.com.

[PS] there is a detail page father and son are to be set document.domain in order to be accessible to each other, is not a single cross-domain. document.domain Features: can be set only once; you can only change the domain part, can not change the port number, and protocol; source port to reset the default port for the protocol.

Principles and procedures

  1. Create a sub-domain, such as api.demo.com (demo.com page in main domain);
  2. Need a proxy under sub-domain file proxy.html, set it document.domain = 'demo.com', and may contain initiate ajax tools;
  3. All API addresses are in api.demo.com;
  4. The primary domain requires requesting the page which is provided document.domain = 'demo.com';
  5. New iframe tag linked to the proxy page;
  6. When sub-pages within the iframe ready, parent page can be used to initiate a sub-page ajax request.

Proxy subdomains flow chart

// 最简单的代理文件proxy.html
<!DOCTYPE html>
<html>
    <script>
        document.domain = 'demo.com';
    </script>
    <script src="jquery.min.js"></script>
</html>
// 新建iframe
var iframe = document.createElement('iframe');
// 链接到代理页
iframe.src = 'http://api.demo.com/proxy.html';
// 代理页就绪时触发
iframe.onload = function(){
  // 由于代理页已经和父页设置了相同的源,父的脚本可以调用代理页的ajax工具;
  // 由于是在子页面发起,其请求地址就跟子页面同源了。
  iframe.contentWindow.jQuery.ajax({
    method: 'POST',
    url: 'http://api.demo.com/products',
    data: {
      product: id,
    },
    success: function(){
      document.body.removeChild(iframe);
      /*...*/
    }
  })
}
document.getElementsByTagName('head')[0].appendChild(iframe);

to sum up

advantage:

  • You can send any type of request;
  • You can use REST-based API specification.

Disadvantages:

  • Not suitable for third-party API, to the second party is less convenient;
  • iframe greater impact on browser performance;
  • You can not use the default port of non-protocol API.

Form analog form

form表单的target属性可以指定一个iframe,使主页面不跳转,而iframe内跳转,所以这个方法的核心就是利用表单提交,并在iframe中获取数据
要访问iframe内外页面互访也是必须设置同源,这点与子域代理是相似的;而iframe内回调父页面,又与JSON-P相似,可以说是两个思路的合体版。
form表单提交后返回的是页面,所以与JSON-P不同的是,返回的是包含了自带填充功能的JavaScript脚本的页面,说起来有点绕,简单来说就是把JSON-P返回的脚本放到一个html页面里自运行。
相比子域代理的方法,它不需要代理页

【PS】form表单提交的特点就是会导致整个页面跳转,返回数据是在新的页面上,这样自然不会产生跨域的问题。

原理及流程

  1. 新建一个子域,比如api.demo.com(页面在主域名demo.com下);
  2. 所有API地址都是在api.demo.com;
  3. 把需要发请求的主域页面设置其document.domain = 'demo.com'
  4. 先定义好父页面上的回调函数;
  5. 新建iframe标签并指定名字;
  6. 新建表单form标签,指定target为刚才的iframe,并添加数据;
  7. 提交表单,iframe内跳转,其中自运行脚本调用了父页面的回调函数。

Analog flowchart form form

// 新建并隐藏iframe
var frame = document.createElement('iframe');
iframe.name = 'post-review';
frame.style.display = 'none';

// 新建表单
var form = document.createElement('form');
form.action = 'http://api.demo.com/products';
form.method = 'POST';
form.target = 'post-review';
// 添加数据
var score = document.createElement('input');
score.name = 'score';
score.value = '5';
// 添加数据
var message = document.createElement('input');
message.name = 'message';
message.value = 'hello world';
// 把数据加到表单
form.appendChild(score);
form.appendChild(message);
// 渲染iframe和表单
document.body.appendChild(frame);
document.body.appendChild(form);
// 提交表单发起请求
form.submit();
// 完成清理元素
document.body.removeChild(form);
document.body.removeChild(frame);
// 最简单返回html
<!DOCTYPE html>
<html>
    <script>
        document.domain = 'demo.com';
        window.parent.jsonpCallback('{"status":"success"}');
    </script>
</html>

总结

由于这个方法是JSON-P与子域名代理的结合版,可以说即拥有两者的优点,也保留了两者一些缺点。

优点:

  • 可以发送任意类型的请求;
  • 不需要代理页;
  • 支持上古级别的浏览器(IE8-)。

缺点:

  • 不太适合第三方API,给第二方使用较麻烦;
  • iframe对浏览器性能影响较大;
  • 无法使用非协议默认端口的API;
  • 需要特殊接口支持,不能基于REST的API规范。

window.name

这方法利用了window.name的特性:一旦被赋值后,当窗口被重定向到一个新的URL时不会改变它的值。这一行为使得不同域的特定文档可以读取该属性值,因此可以绕过同源策略并使跨域消息通信成为可能。

【PS】例子里演示的是发起get请求,只要把请求地址直接写到src里就行了。如果想要发起其他类型的请求,可以类比采用模拟的form的方式进行改造。

原理及流程

  1. 新建iframe,使用iframe访问一个非同源的地址(发请求);
  2. 当页面加载完成后,iframe内脚本给window.name属性赋值,这时父页面还是不能读取到子页面的属性(因为不同源);
  3. iframe自身回调到一个同源的地址(可能只是个空白页),这时候window.name没有改变;
  4. 父页面顺利读取window.name的值。

window.name flow chart

// 新建iframe
var iframe = document.createElement('iframe');
var body = document.getElementByTagName('body');
// 隐藏iframe并链接地址
iframe.style.display = 'none';
iframe.src = 'http://api.demo.com/server.html?id=1';
// 因为需要两次跳转,这里有个完成标记
var done = fasle;
// 这里会触发至少两次,一次由于非同源是取不到值的。
iframe.onload = iframe.onreadystatechange = function(){
    if(! this.readyState && (iframe.readyState !== 'complete' || done)){
        return;
    }
    console.log('Listening');
    var name = iframe.contentWindow.name;
    if(name){
        console.log(iframe.contentWindow.name);
        done = true;
    }
};
body.appendChild(iframe);
// 最简单返回html
<!DOCTYPE html>
<html>
    <script>
    function init(){
        window.name = 'hello';
        window.location = 'http://demo.com/empty.html'
    }
    </script>
    <body onload="init();"></body>
</html>

总结

优点:

  • 可以发送任意类型的请求;
  • 不需要设置子域名。

缺点:

  • iframe对浏览器性能影响较大;
  • 需要特殊接口支持,不能基于REST的API规范;
  • 每当你想要获取一条新的消息时都不得不发起两次网络请求,网络成本大;
  • 需要准备空白页,对它的访问是无意义的,影响流量统计。

window.hash

这个方法利用了location的特性:不同域的页面,可以写不可读。而只改变哈希部分(井号后面)不会导致页面跳转。也就是可以让父、子页面互相写对方的location的哈希部分,进行通讯。

原理及流程

  1. 新建iframe,使用iframe访问一个非同源的地址(发请求),参数里带上父页面url;
  2. 当页面加载完成后,iframe内脚本设置父页面的url并在哈希部分带上数据;
  3. 父页面的脚本循环检查哈希值的变化,如果检查到有值就取值并清空哈希值;
【PS】父页面会循环检查哈希是否改变来读取值,因为这种降级方案的使用环境一般是不会有hashchange事件的。演示里是最简单的get方法,如果想要发起其他类型的请求,可以类比采用模拟的form的方式进行改造,但记住不要丢失父页面的url。

window.hash flow chart

// 获取当前url
var url = window.location.href;
// 新建iframe
var iframe = document.createElement('iframe');
// 隐藏iframe并设置链接,把当前url带上
iframe.style.display = 'none';
iframe.src = 'http://api.demo.com/server.html?id=1&url=' + encodeURIComponent(url);

var body = document.getElementByTagName('body')[0];
body.appendChild(iframe);
// 循环监听处理
var listener = function(){
    // 读取
    var hash = location.hash;
    // 还原
    if(hash && hash !== '#'){
        console.log(hash.replace('#', ''));
        window.loacation.href = url + '#';
    }
    // 继续监听
    setTimeout(listener, 100);
};
listener();
// 最简单返回html
<!DOCTYPE html>
<html>
    <script>
    function init(){
        // 剪裁出父页面的url
        var parentUrl = '';
        var url = window.location.href;
        var str = url.split('?')[1].replace('?', '');
        strs = str.split("&");
        for(var i = 0; i < strs.length; i ++) {
            if(strs.split("=")[0] === 'url'){
                parentUrl = strs.split("=")[1];
            }
        }
        // 设置到父页面上
        window.parent.location = decodeURIComponent(parentUrl) + '#helloworld';
    }
    </script>
    <body onload="init();"></body>
</html>

总结

优点:

  • 可以发送任意类型的请求;
  • 不需要设置子域名。

缺点:

  • iframe对浏览器性能影响较大;
  • 需要特殊接口支持,不能基于REST的API规范;
  • 循环检查哈希需要消耗性能;
  • Return data by the browser URL length maximum 2083 character limit.

Modern standards

W3C standardization of cross-domain solutions, modern browsers allow cross-domain complex matter what is not. This part of the online information for many, here only briefly.

HEARTS

CORS is a W3C standard, stands for "Cross-Origin Resource Sharing" (Cross-origin resource sharing) .
It allows the browser to cross the source server, issued a request XMLHttpRequest, which overcomes the limitations of AJAX only homologous use.

CORS reference document
cross-domain resource sharing CORS Comments

postMessage

The H5 window.postMessage brings a secure browser. Api event-based messages.
As long as the window object, you can use this basic method, that window.name, window.hash such operations have become the trend of the relegation scheme.

postMessage reference documentation

safe question

All the types of non-standard Sao operation, are regarded as a way to break the same-origin policy, in enabling developers to easily complete cross-domain purposes at the same time, all kinds of malicious attackers will naturally take advantage of these programs all kinds of evil.
Which subdomain agent lowest risk, because of the need to set a specific sub-domain name server, which is already the outcome of the consultations the two sources, the hackers are generally difficult to simulate.
The highest risk to count JSON-P program, because this is the way to be free to use any client, the core CSRF attacks also takes advantage of cross-domain request of initiating a particular tag, it is best to use JSON-P in the absence of user the state of the low-security API.

Guess you like

Origin www.cnblogs.com/baimeishaoxia/p/11956611.html