【我不是熟悉的javascript】使用postMessage+iframe实现授权登录, 适用于不同站点,不同域名

需求

从A网站,跳转到B网站,并且把A网站的登录token,带到B网站,使B网站处于登录状态

【此方法 如果使用cookie作为登录状态,在A、B为非同站点(SameSite)的情况下不会生效,因为iframe 在非 同站点 的情况下无法携带cookie, 参考参考

所以可以使用localstorage,localstorage在iframe中使用没有限制, 但是localstorage二级域名和根域名不能共享,除非手动在二级域名下设置document.domain = “根域名”!在iframe中更新localstorage会会被同步更新到网站中

实现方法

  1. 在A网站,设置跳转按钮Button
  2. 在A网站,点击Button,创建一个display:none的iframe,将iframe的 src = B网站的授权登录页面authPage
  3. 在A网站,监听message事件
  4. 在B网站的authPage,监听message事件
  5. 在B网站的authPage,初始化 onload / mounted 之后,使用postMessage发送消息 isReady
  6. 在A网站监听的 message 事件,监听到isReady消息,使用postMessage发送消息setToken
  7. 在B网站的 authPage 监听的 message 事件,监听到setToken消息,使用该token进行登录等一系列操作
  8. B网站登录之后,使用postMessage发送消息close
  9. 在A网站中监听的message事件,监听到close消息,使用location.href跳转到B网站
  10. 此时A,B都使用同一个token,处于登录状态

A网站的代码

// A网站 Button按钮的方法
function openB() {
    const iframeEle = document.createElement('iframe');
    iframeEle.src = `https://B.com/authPage?t=${Math.random(1, 100)}`;
    iframeEle.id = 'iframeEle';
    iframeEle.setAttribute('data-url','https://B.com/');
    iframeEle.style.display = 'none';
    document.body.appendChild(iframeEle);
}

// A 网站中 test.vue的mounted()方法 (或者其他的初始化方法)

function mounted() {
    // 监听message方法
    window.addEventListener('message', receiveMessage);
}


function receiveMessage(e) {
    const iframeEle = document.getElementById('iframeEle');
    if (e.data?.action === 'isReady') {
        iframeEle.contentWindow.postMessage(
                    {
                        token: 'this is your token in A website',
                        action: 'setToken'
                    },'*');
     }
     if (e.data?.action === 'close') {
         const url = iframeEle.getAttribute('data-url');
         document.body.removeChild('iframeEle');
         // 接收到关闭消息时,跳转到B网站
         window.location.href = url;
     }
}

B 网站的代码

// B 网站的mounted方法
function mounted() {
    // window.parent 说明是在iframe中引入的
    if (window.parent) {
		window.parent.postMessage({ action: 'isReady' }, '*')
		window.addEventListener('message', receiveMessage, false)
	}
}

function receiveMessage(e) {
    if (e.data && e.data.action === 'setToken') {
        // 使用新token 登录
        loginByToken(e.data.token).finally(() => {

            // 注意,这里要在loginByToken里面的异步请求,都完成之后才发送close消息
            // 否则,如果loginByToken中的请求没返回,就发消息让A网站执行跳转操作
            // B网站就不会登录成功,因为未返回的请求被浏览器给取消了!!
		    e.source.postMessage({ action: 'close' }, '*')
		})
    }

}

关于postMessage的相关知识请看官网

Window.postMessage() - Web APIs | MDNThe window.postMessage() method safely enables cross-origin communication between Window objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage

扩展知识

1. 同源和同站的区别

彻底搞懂「同源same-origin」和「同站same-site」的区别 - 掘金TLD 表示顶级域名,例如 .com、.org、.cn 等等,不过顶级域名并不是一成不变的,会随着时间推移增加,例如前段时间就增加了 .gay 顶级域名,可以说是广大同性交友爱好者的福音,目前所有顶级域名被收录到了顶级域名数据库里面。 eTLD 由 Mozilla 维护在公共后…https://juejin.cn/post/68774967815052001422. cookie 的same-site 限制

Cookie 的 SameSite 属性 - 阮一峰的网络日志https://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值