【前端】iframe嵌入单点登录链接后,一直访问登录页面?


在这里插入图片描述

问题描述

有这么一个功能,上游系统通过iframe把我们系统的页面嵌入到他们页面内,于是我们需要提供一个链接,点击链接跳转到这个页面后,会去路由中获取用户信息,调接口进行登录操作,获取token信息返回给当前页面,并将token信息缓存起来,后续请求时带上一个token就可以了,在功能实现后,在浏览器上面粘贴我们的地址就可以登录进去,本以为万事大吉,然后看看是否有跨域的问题,顺便就测试了一下在nginx的环境下,是否能够正常登录。

http://10.0.0.1:8081/#/ssoLogin?code=xxx

整了一个html页面,里面有个iframe标签,配的是我们下方的地址,扔到nginx里面,却发现始终会进入我们系统的登录页面,却不会登录到系统里面。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SSO Login</title>
    <style>
        /* 你可以在这里添加样式 */
        body, html {
            margin: 0;
            padding: 0;
            width: 100%;
            height: 100%;
        }
        iframe {
            width: 100%;
            height: 100%;
            border: none;
        }
    </style>
</head>
<body>
    <iframe src="http://10.0.0.1:8081/#/ssoLogin?code=xxx"></iframe>
</body>
</html>

在这里插入图片描述

解决方案

先上答案,感兴趣在往下看吧
我们使用的缓存token的方式是cokkie,

Cookies.set(TokenKey, token)

不曾想到,cokkie只能在同一域名下的所有窗口和标签页之间共享,而iframe时正好是两个ip,一个localhost的html和10.0.0.1的前端访问。所以token无法共享,页面没有token所以路由守卫自动跳转到了登录页面。
后改成sessionStorage,问题解决。

sessionStorage:仅在同一窗口或标签页中共享,不同窗口或标签页之间不共享。
Cookies:在同一域名下的所有窗口和标签页之间共享

  • Chrome浏览器
  • VUE + Element前端页面
  • Nginx

排查过程

1. 怀疑是X-Frame-Options

由于之前碰到过iframe嵌入页面时,若被嵌入页面的nginx有安全限制,则无法被iframe。所以我第一时间就往这里想了,而且之前的时候是明确有这个报错信息的,这次在控制台却没有看到任何保持信息。

在nginx中加入下面的配置,发现无事发生。

add_header X-Frame-Options ALLOWALL; 

后面尝试了其他的方式进行排查。

其实从开始我就应该想到不是这个原因,因为浏览器还能跳转到登录页面,并且控制台没有报错日志。

2. 怀疑是Nginx配置问题导致的跨域

奇怪的是,并没有看到控制台跨域的报错,只能排除掉了

3. 怀疑是代码问题

这次我从头开始了断点调试,首先在ssoLogin页面,加载时会执行获取token方法

openFullScreen2() {
      const loading = this.$loading({
        lock: true,
        text: 'Loading',
        spinner: 'el-icon-loading',
        background: 'rgba(0, 0, 0, 0.7)'
      })

      this.$store
          .dispatch('user/ssoLogin', this.loginForm)
          .then(() => {
            this.$router.push({ path: '/loginSuccess' })
            loading.close()
          })
          .catch(() => {
            loading.close()
          })
    }

获取token之后,对token进行缓存

ssoLogin({ commit }, userInfo) {
    const { code } = userInfo
    return new Promise((resolve, reject) => {
      ssoLogin({ code: code }).then(response => {
        const { data } = response

        commit('SET_TOKEN', data.tokenType + ' ' + data.token)
        setToken(data.tokenType + ' ' + data.token)

        const userInfo = data.userId

        commit('SET_USER_INFO', userInfo)

        resolve()
      }).catch(error => {
        reject(error)
      })
    })
  },
export function setToken(token) {
  return Cookies.set(TokenKey, token)
}

此时我还没有意识到cookie只能在同源的域名下共享,然后断点到路由守卫js,发现走的case还是没有获取到token,这是我才意识到问题所在,将Cookies改成了sessionStorage。之后问题就解决了。

export function setToken(token) {
  return Cookies.set(TokenKey, token)
}

换成

export function setToken(token) {
  return sessionStorage.setItem(TokenKey, 'token)
}

总结

sessionStorage:仅在同一窗口或标签页中共享,不同窗口或标签页之间不共享。
Cookies:在同一域名下的所有窗口和标签页之间共享

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值