关于使用 Iframe 进行跨域访问 localstorage 的问题。
A 页面:http://127.0.0.1:5173/localstorage. 新窗口打开进行 localstorage.setItem("token", "test")
B页面:http://localhost:7456/localstorage.html 中想要访问 A 页面的 localstorage.
方法尝试使用 iframe和 postMessage进行传递。
在 B 页面使用 iframe 打开 A 页面,进行消息传递这些都没有问题。
关键问题:单独使用新窗口打开 A 页面localstorage.getItem("token")是有值的,但是使用 iframe 中打开 A 页面,就无法获取他的 localstorage。查看源是没有问题的啊
浏览器环境:Chrome,不是无痕模式。
希望有大佬帮忙解决一下这个问题。
如果把 A 页面的地址换成 http://localhost:5173/localstorage
或者把 B 页面的地址换成http://127.0.0.1:7456/localstorage.html
一切正常,但是这不就是同源了吗
添加截图和代码
这是单独窗口打开 A 页面,使用 127.0.0.1 打开。可以获取 localstorage
这是 B 页面,使用 localhost:80802 打开。使用 iframe 打开 http://127.0.01:80801/a.html 却不能访问 A 的 localstorage
如果将 B 使用 http://127.0.0.1:8082/b.html 打开,就可以获取的到
代码部分:
a.html
<html>
<header>
A Page
</header>
<body>
<script type="text/JavaScript">
window.addEventListener('message', function (event) {
if (event.origin === "http://127.0.0.1:8081")
return;
const localStorage = window.localStorage.getItem("test")
console.log("localStorage data is: " + localStorage)
// 监听父窗口发送过来的数据向服务器发送post请求
const data = event.data
console.log(event)
const localData = window.localStorage.getItem('test')
console.log(localData)
window.parent.postMessage(localData, "*");
}, false)
</script>
</body>
</html>
B.html
<html>
<header>
B Page
</header>
<body>
<script type="text/JavaScript">
const iframe = document.createElement('iframe')
iframe.src = 'http://127.0.0.1:8081/a.html'
document.body.appendChild(iframe)
window.addEventListener("message", function (event) {
if (event.origin !== "http://127.0.0.1:8081")
return;
const data = event.data;
console.log(event);
}, false);
// window.onload = function () {
// window.frames[0].postMessage("hello", 'http://127.0.0.1:8081')
// }
setTimeout(() => {
iframe.contentWindow.postMessage("hello", 'http://127.0.0.1:8081')
}, 3000)
</script>
</body>
</html>
可以获取到啊,看看你是不是有一些其他的业务代码影响到了?
还是说你的
Storage
里面本来就是空的,所以你获取不到?Edit 01/15/24
补充使用
localhost:8080
访问127.0.0.1:8081
截图:Edit 01/16/24
所以OP其实想要做单点登录,那么简单的如果是同一个顶级域名下的不同的子域名。可以通过在设置
Cookie
时把domain
设置为顶级域名。这样就会应用到顶级域名下的所有子域名。如果不是同一个顶级域名下的,那么就是通过CAS的方式来实现单点登录,简易流程如下:
CAS server
登录页让用户登录;Service Ticket
,并将 Ticket 作为参数携带跳转回应用;单点登录(SSO)看这一篇就够了