踩坑vue项目中使用 iframe 嵌套子系统无法登录,不报错问题!

前言

最近项目中使用了 iframe 标签进行嵌套子系统时,遇到了无法登录、而且不报错的问题。本文记录自己的踩坑过程,也希望帮助到其他同学。

需求

有两个项目,a项目 和 b项目。 当前开发的 a 项目中需要嵌套展示已上线的 b 项目内容; 且要求 b 项目的功能可以正常使用。

遇到问题

在 a 项目中直接使用 iframe 标签进行嵌套 b 项目来展示。且两个项目部署在不同的服务器下。

  • a 项目:88 服务器
  • b 项目:89 服务器

调试中a 项目可以正常跳转到 b 项目,也能在 iframe 中展示出来, 直接跳转到b 项目的 login 页面后正常调用了登录接口, 且登录接口 200 通了, 返回了用户信息。

但是到这里就没有任何执行了,不会在登录成功后跳转到 b项目的系统首页。

问题分析

页面也没有任何报错,接口也都是通的。 卧槽? 这什么问题?

经过反复测试确实没有任何报错,接口也通了,token等用户信息也正常拿到了,就是不跳转 b 系统首页。

但是我发现当 ifreameurl 加载 b项目地址成功显示出 login 登录页面后,点击登录时,页面还会正常走登录接口,此时页面会进行刷新一下 ,也可以获取到 token 等信息,但还是不跳转对应首页。

此时我第一想法就是可能登录成功后被拦截了,导致无法跳转到 home 页。 难道是服务器给拦截了吗?

于是我上网查资料,得到的结果大部分都说是:这种 iframe 嵌套场景因为浏览器的限制,一些 cookie 信息会被拦截导致重定向到了 login 无法正常登录跳转。

问题原因

  • 第三方 Cookie 限制(主要问题)

    • 现代浏览器(Chrome >=80, Safari, Firefox)默认阻止跨域 iframe 的第三方 Cookie
    • 登录依赖的 Session/Cookie 被浏览器阻止写入
  • 同源策略限制

    • iframe 加载的页面与父页面不同源时,无法共享认证状态
  • X-Frame-Options 响应头

    • 目标页面可能设置了 X-Frame-Options: SAMEORIGIN 阻止嵌入
  • 登录逻辑差异

    • iframe 环境可能导致 JS 执行上下文差异(如 window.top 获取失败等问题)

关键代码

先开始我想到这个项目没用到 cookie 相关内容啊。 为了确定,于是尝试在项目里全局查找一下 cookie看看,果然发现了一个文件中包含如下代码:

js 复制代码
import Cookies from 'js-cookie'
const TokenKey = 'saber-access-token'
const RefreshTokenKey = 'saber-refresh-token'
export function getToken() {
    return Cookies.get(TokenKey)
}

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

export function getRefreshToken() {
  return Cookies.get(RefreshTokenKey)
}

export function setRefreshToken(token) {
  return Cookies.set(RefreshTokenKey, token)
}

export function removeToken() {
    return Cookies.remove(TokenKey)
}

export function removeRefreshToken() {
  return Cookies.remove(RefreshTokenKey)
}

发现该项目使用了 js-cookie 来进行存储 token 等用户信息。

问题解决

经过踩坑,查资料总结一下几种解决方案:

方案1: 确保同源或同站

如果条件允许的话,让 iframe 子内容 和 父页面系统 使用相同的域名(或者至少是相同的顶级域名+相同的协议):

  • 父页面系统: https://app.example.com
  • iframe 子系统: https://service.example.com

方案2: 服务器设置 SameSite

主动设置 SameSiteSet-Cookie:Key=Value; SameSite=None; Secure确保协议为安全协议https

  • Java (Servlet) 配置示例
java 复制代码
Cookie cookie = new Cookie("sessionid", "12345");
cookie.setSecure(true);
cookie.setHttpOnly(true);
cookie.setAttribute("SameSite", "None");
response.addCookie(cookie);
  • Nginx 配置示例
arduino 复制代码
location / {
    proxy_pass http://backend;
    proxy_cookie_path / "/; SameSite=None; Secure";
}

方案3: 禁用浏览器 SameSite 默认限制 (仅测试用)

这只适用于开发和测试环境,不要在生产环境中使用。

  • Chrome 启动参数
ini 复制代码
chrome --disable-features=SameSiteByDefaultCookies
  • 注意事项
  1. 必须使用 HTTPSSameSite=None 必须与 Secure 属性一起使用,网站必须使用 HTTPS
  2. 浏览器兼容性:检查需要支持的浏览器版本是否支持 SameSite 属性
  3. 测试验证:在 Chrome 开发者工具的 Application > Cookies 部分检查 Cookie 是否正确设置了 SameSite 属性

修改原项目中使用的 cookie 相关代码。直接弃用 js-cookie,使用 localStorage 来存储用户信息。

js 复制代码
// import Cookies from 'js-cookie'
const TokenKey = 'saber-access-token'
const RefreshTokenKey = 'saber-refresh-token'
export function getToken() {
  // return Cookies.get(TokenKey)
  return localStorage.getItem(TokenKey)
}

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

export function getRefreshToken() {
  // return Cookies.get(RefreshTokenKey)
  return localStorage.getItem(RefreshTokenKey)

}

export function setRefreshToken(token) {
  // return Cookies.set(RefreshTokenKey, token)
  return localStorage.setItem(RefreshTokenKey,token)

}

export function removeToken() {
    // return Cookies.remove(TokenKey)
    return localStorage.remove(TokenKey)
}

export function removeRefreshToken() {
  // return Cookies.remove(RefreshTokenKey)
  return localStorage.remove(RefreshTokenKey)
}

总结

我使用了方案4最简单的方式,直接弃用 js-cookie,改用 localStorage。重新将 b 项目打包部署后,在 a 项目的 iframe 标签内进行嵌套展示,发现登录成功后正常跳转到了 b 项目的首页,且功能正常。

相关推荐
明月_清风1 天前
模仿 create-vite / create-vue 风格写一个现代脚手架
前端·后端
aou1 天前
让表格式录入像 Excel 一样顺滑
前端·ai编程
前端付豪1 天前
必知 Express和 MVC
前端·node.js·全栈
重铸码农荣光1 天前
CSS 也能“私有化”?揭秘模块化 CSS 的防坑指南(附 Vue & React 实战)
前端·css·vue.js
南囝coding1 天前
CSS终于能做瀑布流了!三行代码搞定,告别JavaScript布局
前端·后端·面试
ccnocare1 天前
git 创建远程分支
前端
全栈王校长1 天前
Vue.js 3 项目构建神器:Webpack 全攻略
前端
1024小神1 天前
cloudflare+hono使用worker实现api接口和r2文件存储和下载
前端
Anita_Sun1 天前
Lodash 源码解读与原理分析 - Lodash 对象创建的完整流程
前端
米诺zuo1 天前
TypeScript 知识总结
前端