陈菊华 發表於 2022-4-1 22:42:00

利用iframe实现不同域名间共享localStorage/sessionStorage

<h1 id="概要">概要</h1>
<blockquote>
<p>在实际开发场景中,有时我们会遇到不同域名下实现状态共享的类似需求,我们知道两个不同的域名的localStorage是不能直接互相访问。那么如何在projectA.com中调用projectB.com的localStorage呢,本文手把手带你实现。</p>
</blockquote>
<h1 id="实现原理">实现原理</h1>
<ul>
<li>1.在projectA.com的页面中,嵌入一个src为projectB.com的iframe,此时这个iframe里可以调用projectB.com的localStorage。</li>
<li>2.用postMessage方法实现页面与iframe之间的通信。</li>
</ul>
<p>综合1、2便可以实现projectA.com中调用projectB.com的localStorage。</p>
<h1 id="实现demo">实现demo</h1>
<p>我们可以在projectB.com中写一个专门负责共享localStorage的页面,例如叫做share.html,这样可以防止无用的资源加载到iframe中。</p>
<p>以在projectA.com中读取projectB.com中的localStorage的token为例。<br>
projectB.com中share.html,监听projectA.com通过postMessage传来的信息,读取localStorage,然后再使用postMessage方法传给projectA.com的接收者。<br>
在localstorage-&gt;projectB目录下新建share.html, 在localstorage-&gt;projectA目录下新建project-a.html。<br>
在projectA.com的页面中加入一个src为projectB.com/share.html的iframe。<br>
在projectA.com的页面中加入下面script标签。在页面加载完毕时通过postMessage告诉iframe中监听者,读取token。监听projectB.com传回的token的值并输出。<br>
代码如下:</p>
<h2 id="sharehtml">share.html</h2>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&gt;
&lt;title&gt;project B&lt;/title&gt;
&lt;style type="text/css"&gt;
    body {
      margin: 0;
      padding: 0;
      height: 100%;
      width: 100%;
      margin: 0 auto;
    }
    h1 {
      width: 100%;
      color: red;
      white-space: nowrap;
    }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
    &lt;h1&gt;This page is for sharing localstorage.&lt;/h1&gt;
    &lt;script type="text/javascript"&gt;
      localStorage.setItem('token', 'token-value')
      window.addEventListener('message', function (evt) {
      if (evt.origin === 'http://192.168.1.4:8081') {
          console.log("接收到了project A的请求")
          const value = localStorage.getItem('token')
          evt.source.postMessage({token: value}, evt.origin)
      }
      }, false)
    &lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h2 id="project-ahtml">project-a.html</h2>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;
&lt;head&gt;
&lt;meta charset="UTF-8"&gt;
&lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
&lt;meta http-equiv="X-UA-Compatible" content="ie=edge"&gt;
&lt;title&gt;project A&lt;/title&gt;
&lt;style type="text/css"&gt;
    body {
      margin: 0;
      padding: 0;
      height: 100%;
      width: 100%;
    }
    iframe {
      width: 100%;
      margin: 0 auto;
    }
&lt;/style&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;iframe id="JS_iframe" src="http://192.168.1.4:8080/share.html" frameborder="0"&gt;&lt;/iframe&gt;
&lt;button id="JS_button"&gt;获取token&lt;/button&gt;
&lt;script type="text/javascript"&gt;
    const buttonEl = document.querySelector('#JS_button')
    buttonEl.addEventListener('click', function (evt) {
      const iframeEl = document.querySelector("#JS_iframe")
      iframeEl.contentWindow.postMessage({ auth: 'admin' }, 'http://192.168.1.4:8080/share.html')
    }, false)

    window.onload = function () {
      const iframeEl = document.querySelector("#JS_iframe")
      iframeEl.contentWindow.postMessage({ auth: 'admin' }, 'http://192.168.1.4:8080/share.html')
    }
   
    window.addEventListener('message', function (evt) {
      if (evt.origin === 'http://192.168.1.4:8080') {
      console.log("收到projectB的消息:", evt.data)
      }
    }, false)
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre>
<h1 id="测试demo">测试demo</h1>
<p>全局安装<code>npm install -g http-server</code>,在cmd控制台分别进入projectB和projectA目录运行http-server -c-l启动两个服务。<br>
<img src="https://img2022.cnblogs.com/blog/2448697/202204/2448697-20220401223914352-1450199142.png" alt="" loading="lazy"></p>
<p>在浏览器访问,点击获取token按钮测试<br>
<img src="https://img2022.cnblogs.com/blog/2448697/202204/2448697-20220401224002470-2142375419.png" alt="" loading="lazy"></p><br><br>
来源:https://www.cnblogs.com/smart-elwin/p/16089531.html
頁: [1]
查看完整版本: 利用iframe实现不同域名间共享localStorage/sessionStorage