2017-10-06 515 views
0

我有两种不同的网站siteA.com和siteB.com,当访问者浏览时需要共享一条信息siteA到siteB。我无法访问站点A的服务器端代码或导航链接,只能限制自定义设置和JavaScript。为了分享这些信息,我建立了一个完全由siteC.com控制的新页面,然后将此页面作为iframe添加到siteA和siteB。我正在使用postMessage方法来从每个站点工作正常的iframe中获取和设置cookie,但实际上我最终得到了两个不同的cookie,每个站点A和站点B都有一个cookie,即使Cookie属于siteC,因为它是由iframe中的页面设置,通过F12调试器进行确认。我预计会有一个cookie,这两个网站可以通过iframe共享相同的cookie,我是否在这里丢失了某些东西,是否应该这样做,或者有另一种方法可以做到这一点?试图在使用常见iframe的域名之间共享cookie,但是却获得了两个cookie

这是我的网页在思泰科是被加载到iframe中

<!DOCTYPE html> 
<html> 
<head> 
    <title>iframe source</title> 
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> 
    <script type="text/javascript"> 
     $(function() { 
     var ck = document.cookie; 
     var expDate = new Date(); 
     expDate.setFullYear(expDate.getFullYear() + 20) 
     $("#auditlog").append("iframe loaded<br/>"); 
     if (ck) { 
      $("#auditlog").append("cookie exists<br/>"); 
     } else { 
      $("#auditlog").append("cookie not set<br/>"); 
     } 

     // Assign handler to message event 
     if (window.addEventListener) { 
      window.addEventListener('message', messageHandler, false); 
     } else if (window.attachEvent) { // ie8 
      window.attachEvent('onmessage', messageHandler); 
     } 
     }) 

     function messageHandler(e) { 
     var msg = {}; 
     var response; 
     // Check origin 
     if (e.origin === 'http://siteA' || e.origin === 'http://siteB') { 
      // Retrieve data sent in postMessage 
      msg = JSON.parse(e.data); 
      if (msg.action == "getCookie") { 
       response = getCookie(); 
      } else if (msg.action == "setCookie") { 
       setCookie(msg.payload); 
       response = "cookie set"; 
      } else { 
       response = "action not supported"; 
      } 
      // Send reply to source of message 
      e.source.postMessage(response, e.origin); 
     } 
     } 

     function setCookie(cookieVal) { 
     var expDate = new Date(); 
     expDate.setFullYear(expDate.getFullYear() + 20) 
     document.cookie = cookieVal + "; expires=" + expDate.toUTCString(); 
     } 

     function getCookie() { 
     return document.cookie; 
     } 
    </script> 
</head> 
<body> 
    <div id="auditlog"></div> 
    <div id="cookieinfo"></div> 
</body> 
</html> 

的代码,这是我的站点A和站点B的网页代码,两者都使用相同的代码,这是一个示例我建立以测试set和get cookie的功能在iframe

<!DOCTYPE html> 
<html> 
<head> 
    <title>Main content page</title> 
    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script> 
    <script type="text/javascript"> 
     $(function() { 
     // Assign handler to message event 
     if (window.addEventListener) { 
      window.addEventListener('message', messageHandler, false); 
     } else if (window.attachEvent) { // ie8 
      window.attachEvent('onmessage', messageHandler); 
     } 

     $("#btnGetIframeCookie").click(function() { 
      var postMsg = { 
       action:"getCookie" 
      } 
      // get reference to window inside the iframe 
      var wn = document.getElementById('cookieiframe').contentWindow; 
      // postMessage arguments: data to send, target origin 
      wn.postMessage(JSON.stringify(postMsg), 'http://siteC'); 
     }) 
     $("#btnSetIframeCookie").click(function() { 
      var cookieVal = $("#txtCookieValue").val(); 
      var postMsg = { 
       action: "setCookie", 
       payload: cookieVal 
      } 
      var wn = document.getElementById('cookieiframe').contentWindow; 
      // postMessage arguments: data to send, target origin 
      wn.postMessage(JSON.stringify(postMsg), 'http://siteC'); 
     }) 
     }) 

     function messageHandler(e) { 
     if (e.origin === 'http://siteC') { 
      $("#divMessages").append("response from iframe: <br/>" + e.data + "<br/>"); 
     } 
     } 
    </script> 
</head> 
<body> 
    <div> 
     This is the iframe container 
    </div> 
    <div> 
     <input type="button" id="btnGetIframeCookie" value="Get iframe cookie" /> 
    </div> 
    <div> 
     <input type="text" size="60" id="txtCookieValue" /> 
     <input type="button" id="btnSetIframeCookie" value="Set iframe cookie" /> 
    </div> 
    <iframe id="cookieiframe" src="http://siteC/iframe/index.html" style="width: 300px; height: 300px; border:1px solid black;"></iframe> 
    <div id="divMessages"></div> 
</body> 
</html> 

使用这种设置,如果我通过与"keyabc=value123"例如值的iframe,距离站点A一个cookie,然后我就可以读取相同cookie回来,但是当我去siteB有相同的pa ge在iframe那里,我没有cookie,直到我在那里设置一个,例如"keyabc=value456"。现在,如果我查看我的实际cookie文件C:\Users\aakoehle\AppData\Local\Packages\Microsoft.MicrosoftEdge_8wekyb3d8bbwe\AC\#!001\MicrosoftEdge\Cookies,则会看到两个文件,一个包含我设置的每个值,并且都具有siteC的路径。我还为每个浏览器选项卡启动了F12工具,每个选项卡显示属于siteC的Cookie。

- 更新 -

随着我的代码贴在这里,现在我只看到了问题的cookie中的边缘浏览器的最新版本。按照预期,Chrome和IE在siteA和siteB之间共享一个cookie。

+0

您是否尝试过其他方法,比如'localStorage'或'webSQL'或'sessionStorage'? – 11thdimension

+0

我还没有尝试过这些选项,我对它们并不熟悉,但我会研究它,谢谢! – AK3800

+0

我尝试了localStorage,但它的行为与我原来的cookie解决方案相同,我有两个值,每个页面托管iframe。 – AK3800

回答

-1

由于安全问题,Cookie不能设置在两个不同的域中。这就是为什么你得到两个饼干。但是,如果他们共享域,例如a.mywebsite.com和b.mywebsite.com,您可以附加以下内容:;domain=mywebsite.com

您可以做的是在网站C上创建一个getter/setter并从网站A和B调用它。不知道这是否是一个安全的解决方案。

编辑: 我不使用I帧非常熟悉,但你可能想看看:https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

window.postMessage()方法安全地启用了跨源 通信。

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

其中otherWindow是:

到另一个窗口的引用;这样的参考可以被获得, 例如,使用iframe元件

所以的contentWindow属性,下面的代码只是模拟代码予制备。这是未经测试,我从来没有尝试过,因为我不使用iframe的解决方案,我没有在时刻,以测试它的能力:

class CrossCommunicator 
{ 
    constructor(iframeId) 
    { 
     // check if localStorage works on the page or exit (can be done better). 
     if (!localStorage) 
     { 
      console.warn('Your browser does not support localStorage'); 
      return; 
     } 

     // search iframe on the current page. 
     this.usingIFrame = document.querySelector('iframe[id="' + iframeId + '"]'); 

     // create event listener when receiving data. 
     window.addEventListener('message',() => this.onResponse(), false); 
    } 

    onResponse(event) 
    { 
     // do something when you receive stuff. 
     let command = JSON.parse(event.data); 

     if (command.command == 'GET') 
     { 
      let value = localStorage.getItem(command.key); 
      this.set(command.key, value); 
     } 
     else if (command.command == 'SET') 
     { 
      localStorage.setItem(command.key, command.value); 
     } 
    } 

    set(key, value) 
    { 
     window.postMessage(JSON.stringify({ 
           command : 'SET', 
           key  : key, 
           value : value 
          }), 
          this.usingIFrame.contentWindow); 
    } 

    get(key) 
    { 
     window.postMessage(JSON.stringify({ 
           command : 'GET', 
           key  : key 
          }), 
          this.usingIFrame.contentWindow); 
    } 
} 

// usage. note that website C should reference two iframes instead of one.. 
let crossCommunicator = new CrossCommunicator('my-iframe-id'); 
crossCommunicator.get('mykey'); // will trigger postMessage on website C and then trigger message event which is handled by onResponse(). 
+0

这就是我不了解我的设置,我认为通过在siteC的单个页面设置cookie,然后它是一个单独的页面/域,它将在这些站点之间共享。 getter/setter函数在siteC上,它恰好在iframe中托管。 – AK3800

1

这里有一个跨源站点之间共享数据的例子,使用localStoragepostMessage

站点1:本地主机:9091

<html> 
<body> 
    <h1>site 1</h1> 
    <button id='postBtn'>Post message</button> 
    <br/> 
    <iframe id='commonSite' src='http://localhost:9093/commonSite.html' style='height:150px'></iframe> 

    <script> 
     (function() { 
      var commonSite = document.querySelector('#commonSite').contentWindow; 
      var postCounter = localStorage.getItem('postCounter'); 
      postCounter = postCounter != null ? +postCounter : 1; 

      var commonOrigin = 'http://localhost:9093'; 

      document.querySelector('#postBtn').onclick = function() { 
       commonSite.postMessage(postCounter++, commonOrigin); 
       localStorage.setItem('postCounter', postCounter); 

       console.log('site 1 posted'); 
      } 
     })(); 
    </script> 
</body> 
</html> 

站点2:本地主机:9092

<html> 
<body> 
    <h1>site 2</h1> 
    <button id='postBtn'>Post message</button> 
    <br/> 
    <iframe id='commonSite' src='http://localhost:9093/commonSite.html' style='height:150px'></iframe> 

    <script> 
     (function() { 
      var commonSite = document.querySelector('#commonSite').contentWindow; 
      var postCounter = localStorage.getItem('postCounter'); 
      postCounter = postCounter != null ? +postCounter : 1; 

      var commonOrigin = 'http://localhost:9093'; 

      document.querySelector('#postBtn').onclick = function() { 
       commonSite.postMessage(postCounter++, commonOrigin); 
       localStorage.setItem('postCounter', postCounter); 

       console.log('site 2 posted'); 
      } 
     })(); 
    </script> 
</body> 
</html> 

commonSite:本地主机:9093

<html> 
<body> 
    <h3>Common site</h1> 
    <h4> Site 1 count: <span id='count1'></span></h3> 
    <h4> Site 2 count: <span id='count2'></span></h3> 

    <script> 
     (function() { 
      console.log('Adding message listener'); 
      var origin1 = 'http://localhost:9091'; 
      var origin2 = 'http://localhost:9092'; 

      var count1 = document.querySelector('#count1'); 
      var count2 = document.querySelector('#count2'); 

      if(localStorage.getItem('count1')) { 
       count1.textContent = localStorage.getItem('count1'); 
      } 

      if(localStorage.getItem('count2')) { 
       count2.textContent = localStorage.getItem('count2'); 
      } 

      window.addEventListener('message', function (event) { 
       var origin = event.origin; 
       var data = event.data; 

       if(origin === origin1) { 
        localStorage.setItem('count1', data); 
        count1.textContent = localStorage.getItem('count1'); 
       } else if(origin === origin2) { 
        localStorage.setItem('count2', data); 
        count2.textContent = localStorage.getItem('count2'); 
       } 

       console.log('received (' + data + ') from ' + origin); 
      }, false); 
     })(); 
    </script> 
</body> 
</html> 
+0

感谢代码,但是当我设置它时,我在Edge中遇到了同样的问题。 – AK3800

+0

我刚刚在'IE11'上测试过,它工作正常,我的IE是显示文件。我稍后必须检查'Edge',因为我目前无法访问它。它已经在研究'Chrome'。我正在实例化'python'简单的服务器来测试'python -m http.server 9091' – 11thdimension

相关问题