IFrame跨域通信的幾種方法

在項目中遇到頁面中嵌入IFrame(主頁面和框架頁爲不一樣域名)時,因爲同源策略,主頁面和IFrame內頁沒法通信的問題。javascript

同源策略是一個很重要的安全理念,它在保證數據的安全性方面有着重要的意義。同源策略規定跨域之間的腳本是隔離的,一個域的腳本不能訪問和操做另一個域的絕大部分屬性和方法。那怎樣是相同的域呢?當兩個域具備相同的協議(如http), 相同的端口(如80),相同的host(如www.example.org),那麼咱們就能夠認爲它們是相同的域。html

查找並實踐了幾種方法,在這裏記錄一下。java

第一種:修改document.domain
跨域的不一樣框架之間(父框架和同輩框架),是可以獲取到彼此的window對象的,可是卻不能獲取到window對象的屬性和方法。在父窗口以及框架頁內設定document.domain = document.domain; 後,兩個頁面間就能夠透過拿到的window對象去互相調用對方方法或屬性。
這種方法適合主域相同,而子域不一樣的場景。這裏有一段解釋: https://developer.mozilla.org...segmentfault

A page may change its own origin with some limitations. A script can set the value of document.domain to its current domain or a superdomain of its current domain. If it sets it to a superdomain of its current domain, the shorter domain is used for subsequent origin checks. For example, assume a script in the document at http://store.company.com/dir/... executes the following statement:
document.domain = "company.com";
After that statement executes, the page can pass the origin check with http://company.com/dir/page.html (assuming http://company.com/dir/page.html sets its document.domain to "company.com" to indicate that it wishes to allow that - see document.domain for more). However, company.com could not set document.domain to othercompany.com since that is not a superdomain of company.com.
The port number is kept separately by the browser. Any call to the setter, including document.domain = document.domain causes the port number to be overwritten with null. Therefore one cannot make company.com:8080 talk to company.com by only setting document.domain = "company.com" in the first. It has to be set in both so that port numbers are both null.

第二種方法:使用window.postMessge跨域

父頁面http://localhost:8081/安全

<body>
    <h1>This is synesiss app</h1>
    <input type="button" name="" value="Call API" onclick="callAPI()">
    <iframe id="childFrame" src="http://localhost:8888/" width="" height=""></iframe>
  </body>
  <script type="text/javascript">
  document.domain = document.domain;

  function callAPI(){
    let receiver = document.getElementById("childFrame").contentWindow;
    receiver.postMessage("callAPI", "http://localhost:8888/");
  }
  </script>

子頁面http://localhost:8888/app

<script>    
window.onload = function(){
      window.addEventListener('message', function(event){
        if (event.origin !== "http://localhost:8081")
          return;
        if(event.data == "callAPI") {
          // do API...
        }
      });
    }
</script>

參考資源: 跨域資源共享的10種方式
新手學跨域之iframe框架

相關文章
相關標籤/搜索