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参数。

  • 12
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当在网页中嵌套使用iframe时,可能会遇到一些问题,如样式冲突、无法调整大小、页面加载速度慢等。下面介绍一些解决iframe嵌套页面问题的方法。 首先,针对样式冲突问题,可以使用CSS命名空间(CSS Namespaces)来解决。通过添加命名空间前缀,可以确保不同iframe中的元素样式不会相互冲突。这样可以避免样式被覆盖,保证每个iframe中的样式独立。 其次,针对调整iframe大小问题,可以使用JavaScript来动态调整iframe的大小。通过监听iframe内部内容的高度变化,并将高度值传递给父页面,从而实现自适应调整iframe的大小。这样可以确保iframe始终能够显示完整的内容,提高用户体验。 另外,针对页面加载速度慢的问题,可以通过延迟加载或者懒加载来提升性能。即在页面初次加载时,只加载展示iframe的占位符,并不加载真正的内容。当用户需要查看或者操作iframe时,再加载对应的内容。这样可以减少初次加载的数据量,提高页面加载速度。 此外,还可以考虑使用无需iframe的其他技术来实现类似的功能,如Ajax、Vue.js等。这些技术可以通过异步加载内容或者组件来避免使用iframe,从而减少了嵌套页面的问题。 综上所述,处理iframe嵌套页面问题需要使用CSS命名空间、动态调整大小、延迟加载或懒加载等方法。同时也可以考虑使用其他技术来避免使用iframe带来的问题。通过采取这些方法,可以更好地解决iframe嵌套页面问题,提升用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值