需求
从A网站,跳转到B网站,并且把A网站的登录token,带到B网站,使B网站处于登录状态
【此方法 如果使用cookie作为登录状态,在A、B为非同站点(SameSite)的情况下不会生效,因为iframe 在非 同站点 的情况下无法携带cookie, 参考,参考】
所以可以使用localstorage,localstorage在iframe中使用没有限制, 但是localstorage二级域名和根域名不能共享,除非手动在二级域名下设置document.domain = “根域名”!在iframe中更新localstorage会会被同步更新到网站中
实现方法
- 在A网站,设置跳转按钮Button
- 在A网站,点击Button,创建一个display:none的iframe,将iframe的 src = B网站的授权登录页面authPage
- 在A网站,监听message事件
- 在B网站的authPage,监听message事件
- 在B网站的authPage,初始化 onload / mounted 之后,使用postMessage发送消息 isReady
- 在A网站监听的 message 事件,监听到isReady消息,使用postMessage发送消息setToken
- 在B网站的 authPage 监听的 message 事件,监听到setToken消息,使用该token进行登录等一系列操作
- B网站登录之后,使用postMessage发送消息close
- 在A网站中监听的message事件,监听到close消息,使用location.href跳转到B网站
- 此时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的相关知识请看官网
扩展知识
1. 同源和同站的区别
Cookie 的 SameSite 属性 - 阮一峰的网络日志https://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html