iframe解决跳转登录界面问题
iframe解决跳转登录界面问题前端开发中难免会遇到需要通过iframe嵌入其他界面的需求。这时候如果被嵌入的页面需要登录获取权限,会出现iframe内出现登录页的情况。一般都会要求做到无感知登录。具体如何实现,视情况而定,大致如下:同源环境下,可提前进行登录请求,在localstorage、cookie、session存储token、userId等信息后,进行iframe访问。跨域时较为复杂,需
iframe解决跳转登录界面问题
前端开发中难免会遇到需要通过iframe嵌入其他界面的需求。这时候如果被嵌入的页面需要登录获取权限,会出现iframe内出现登录页的情况。一般都会要求做到无感知登录。具体如何实现,视情况而定,大致如下:
- 同源环境下,可提前进行登录请求,在localstorage、cookie、session存储token、userId等信息后,进行iframe访问。
- 跨域时较为复杂,需要同时修改iframe内外部两个系统,本文主要是解决这种情况
整体思路
1.外部系统调用特定接口获取内部系统的token、userId、userName等信息;
2.通过postMessage()
方法向iframe内部系统传输token等信息;
3.内部系统通过window.addEventListener('message', event => {})
监听传入的message并处理;
4.当内部系统token过期时,通过postMessage()
方法向外部系统传送过期标志;
5.外部系统通过window.addEventListener('message', event => {})
监听关闭iframe页面或者进行其他操作(跳转登录页、重新进行1-3步等)
外部系统
// 必须在onload之后进行通信,不然iframe内部系统可能无法获取参数
this.$refs.iframe.onload = () => {
this.postMessage()
}
window.addEventListener('message', this.listenMessage)
// 发送message
postMessage() {
// 通过某种方式获取登录信息
const ccInfo = oneFunc()
/**
* otherWindow.postMessage(message, targetOrigin, [transfer]);
* message: 将要发送到其他window的数据
* targetOrigin: 指定哪些url能接收消息,“*” 表示无限制,或者是一个URI
* transfer: 是一串和message同时传递的Transferable对象,这些对象的所有权将被转移给消息的接收方,而发送方将不再保留所有权
*/
this.$refs.iframe.contentWindow.postMessage({
type: 'iframe',
data: {
token: ccInfo.token,
userId: ccInfo.userId,
userName: ccInfo.userName,
role: ccInfo.role,
originUrl: location.href, // 这个有用
redirect: '/dashboard',
}
}, '*')
}
// 监听iframe页面传输message
listenMessage(event) {
console.log(`get event from iframe => from: ${event.origin} message: ${event.data}`)
if (event.data && event.data.type === 'iframe' && event.data.expiredToken) {
this.$message({
message: '登录过期',
type: 'error',
})
}
}
主要做3件事:1.获取iframe内部系统的登录信息(交给后台同学);2.向iframe内部系统传登录信息;3.监听内部系统返回的token过期标志。
注意:由于是iframe页面加载完成之后触发的传参,其实此时iframe内部系统其实已经跳转到登录页了!为了避免这种情况,我是通过iframe的src设置为特定路由,不做token校验,没有界面,只监听message,当接收到后续信息之后再重定向到
redirect
内部系统
// 监听信息(特定/iframe路由)
window.addEventListener('message', event => {
if (event.data && event.data.type === 'iframe' && event.data.data.token) {
const data = event.data.data
setToken(data.token)
Cookies.set('is-iframe', true)
Cookies.set('origin-url', data.originUrl)
Cookies.set('Cloud-User-Id', data.userId)
Cookies.set('Cloud-User-Name', data.userName)
Cookies.set('Cloud-User-Role', data.role)
setTimeout(() => {
this.$router.push({ path: data.redirect })
}, 500)
}
})
// 在router跳转到login页之前执行
if (Cookies.get('is-iframe')) {
top.postMessage({
type: 'iframe',
expiredToken: true
}, Cookies.get('origin-url'))
Cookies.set('is-iframe', false)
return
}
做两件事:1.创建特定路由/iframe页,监听message信息,进行同login操作;2.在token过期跳转到login页之前,向外部系统传参。
注意:
top.postMessage
如果不设置targetOrigin
会提示跨域错误。所以需要用到外部系统传入的originUrl
参数。
更多推荐
所有评论(0)