解决第三方使用iframe内嵌页面时无法正常登录访问的问题

news2025/1/17 1:01:59

1. 问题描述

  • 在做项目的时候,可能会遇到需要内嵌第三方页面或者第三方软件厂商内嵌我们自己做的web页面(这里说的内嵌方式是用iframe的方式),当在使用最新版本的“谷歌浏览器”时就会出现无法正常登录的问题,内嵌的页面无法正常的显示,只能显示登录页面,而且输入正确的用户名和密码也无法跳转到展示页面;
  • 我从网上找了很多的博客,发现大部分写的都是原理和一些比较简单的解决方案,试过后也还是没法解决这个问题,有的还很麻烦,所以自己在解决了该问题后,我把自己遇到的问题及问题原因和解决方案详细的写一下,帮助大家很快的解决掉该问题
  • 问题案例:
    公司有个需求,需要将做的各个系统的程序页面集成到一个环境中来,最好的实现方案就是使用iframe内嵌的方式,将其他系统的页面集成到页面中来,但是有个问题,其他系统在登录的时候,都是需要用cookie获取token等跟鉴权相关的信息,如果是使用该种方式,那么在用谷歌88或以上版本访问的时候则不能正常的访问,直接跳转到登录页面,且在该登录页面重新输入用户名和密码后再点击登录,接口会请求成功,但是无法跳转到展示页面。但是用其他除了谷歌内核的浏览器是正常的,比如火狐。

2. 问题原因

  • 经过排查是因为拿不到token,拿不到token的原因是:由于跨域问题导致,我们框架里把token存储在了cookie中,开始我们系统用的cookie存储的token,由于另一个token的信息是在iframe的src中,这样就导致获取不到token。
  • Google 在2020年2月4号发布的 Chrome 80 版本(schedule:https://www.chromestatus/features/schedule)中默认屏蔽所有第三方 Cookie,即默认为所有 Cookie 加上 SameSite=Lax 属性(https://www.chromestatus/feature/5088147346030592),并且拒绝非Secure的Cookie设为 SameSite=None(https://www.chromestatus/feature/5633521622188032), SameSite的作用就是防止跨域传送cookie,从而防止 CSRF 攻击和用户追踪,此举是为了从源头屏蔽 CSRF 漏洞。关于 SameSite 属性的介绍,《Cookie 的 SameSite 属性》。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    上述的问题原因是我从网上找到的写的比较详细一些的,原文连接是:chrome浏览器iframe嵌套页面跨域无法获取cookie问题
    简单来说就是因为谷歌的最新版本导致的该问题,在使用不同ip端口页面访问的时候,无法设置和获取到cookie
    在这里插入图片描述
    因为在嵌套的页面对应的系统中,需要用到cookie去获取token用于接口查询等操作时的请求头中的参数项,所以如果获取不到的时候,就会出现异常,导致无法正常登录、接口无法正常查询
    在这里插入图片描述
    上图是正常请求的情况,能够正常的响应数据,下图是异常的情况,没有传Authorization、Cookie等重要的信息:
    在这里插入图片描述

3. 解决方案

3.1. 因为无法获取到cookie,那么当将cookie中保存的一些信息都保存到sessionStorage或localstorage中的话,就不会存在该问题,所以我就将token信息保存到了sessionStorage中,当获取cookie中的token获取不到的时候,那么再去获取sessionStorage中的token,这样如果sessionStorage中保存了的话,该问题就解决掉了,具体的代码如下:

import Cookies from "js-cookie";
import cache from "@/plugins/cache";

const TokenKey = location.host + "_DcAdmin-Token";

const isDefaultLogin = process.env.VUE_APP_IS_DEFAULT_LOGIN;

export function getToken() {
  let token = "";
  if (!Cookies.get(TokenKey)) {
    token = cache.session.get(TokenKey);
  } else {
    token = Cookies.get(TokenKey);
  }

  return token;
}

export function setToken(token) {
  if (isDefaultLogin == "true") {
    cache.session.set(TokenKey, token);
  }
  return Cookies.set(TokenKey, token);
}

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

VUE_APP_IS_DEFAULT_LOGIN是设置的一个参数,用于设置是否默认登录,即自己在配置文件中设置默认登录的用户名和密码,实现自动登录,也可以是使用单点登录鉴权。在代码中增加“ if (isDefaultLogin == “true”) ”的判断还有一个原因是:不需要在所有情况下都保存到sessionStorage中,只有在需要内嵌系统页面的时候才需要存到sessionStorage,其他情况下不需要保存,保证了系统的安全性,避免被破解攻击,因为使用cookie的安全性比sessionStorage会更高一些。

  • plugins/cache的代码
const sessionCache = {
  set (key, value) {
    if (!sessionStorage) {
      return
    }
    if (key != null && value != null) {
      sessionStorage.setItem(key, value)
    }
  },
  get (key) {
    if (!sessionStorage) {
      return null
    }
    if (key == null) {
      return null
    }
    return sessionStorage.getItem(key)
  },
  setJSON (key, jsonValue) {
    if (jsonValue != null) {
      this.set(key, JSON.stringify(jsonValue))
    }
  },
  getJSON (key) {
    const value = this.get(key)
    if (value != null) {
      return JSON.parse(value)
    }
  },
  remove (key) {
    sessionStorage.removeItem(key);
  }
}
const localCache = {
  set (key, value) {
    if (!localStorage) {
      return
    }
    if (key != null && value != null) {
      localStorage.setItem(key, value)
    }
  },
  get (key) {
    if (!localStorage) {
      return null
    }
    if (key == null) {
      return null
    }
    return localStorage.getItem(key)
  },
  setJSON (key, jsonValue) {
    if (jsonValue != null) {
      this.set(key, JSON.stringify(jsonValue))
    }
  },
  getJSON (key) {
    const value = this.get(key)
    if (value != null) {
      return JSON.parse(value)
    }
  },
  remove (key) {
    localStorage.removeItem(key);
  }
}

export default {
  /**
   * 会话级缓存
   */
  session: sessionCache,
  /**
   * 本地缓存
   */
  local: localCache
}

3.2. 在系统中,不光是token需要存储到cookie中,像用户名、密码等简单的一些信息可能也需要保存到cookie中,那么也需要我们将这些信息保存到sessionStorage中,所以需要写一个公共的设置,统一的设置cookie的信息,具体代码如下:

// 设置cookie的值 解决跨域的问题
export function getCookie(key) {
  let value = "";
  if (!Cookies.get(key)) {
    value = cache.session.get(key);
  } else {
    value = Cookies.get(key);
  }

  return value;
}

export function setCookie(key, value) {
  if (isDefaultLogin == "true") {
    cache.session.set(key, value);
  }
  return Cookies.set(key, value);
}

export function removeCookie(key) {
  cache.session.remove(key);
  return Cookies.remove(key);
}

下面是设置sessionStorage后的效果:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3.3. 浏览器存储值 Cookie、sessionStorage、localstorage的区别,及都在哪些场景中可以使用

首先,Cookie、sessionStorage和localStorage都是用于在浏览器端存储数据的机制,但它们在用途、生命周期和存储容量等方面有一些区别。

  1. Cookie:
    • 生命周期: 可以设置过期时间,可以是会话级的(浏览器关闭就失效)或持久性的(在指定过期日期前有效)。
    • 存储容量: 通常每个Cookie的大小受限制,一般为几KB。
    • 用途: 主要用于在客户端存储会话信息,如用户登录状态、购物车内容等。由于每次请求都会携带Cookie,可能会影响性能。
  2. sessionStorage:
    • 生命周期: 存储在 session 中,页面会话结束时(例如关闭标签页或浏览器)数据被清除。
    • 存储容量: 比Cookie稍大,通常在5-10MB左右。
    • 用途: 适合临时保存一些页面会话期间需要用到的数据,不同页面之间无法共享。
  3. localStorage:
    • 生命周期: 持久性的存储,除非被显式删除或页面被清除,否则数据将一直存在。
    • 存储容量: 比sessionStorage更大,通常在5-10MB左右。
    • 用途: 适合永久性地存储一些本地的用户设置、历史记录等信息,不同页面之间可以共享。
  4. 场景中的使用:
    Cookie: 适合在服务器和客户端之间传递小段数据,比如用户登录状态的保持,购物车信息等。
    sessionStorage: 适合在同一个页面会话期间保持数据,比如表单临时数据,页面之间的传递。
    localStorage: 适合永久性存储,如用户偏好设置、本地缓存数据等。
    综上所述,选择使用哪种存储方式取决于你的需求,是临时性的、会话级的还是需要长期保存的。

4. 总结

上述描述的内容就是我自己的解决方案,主要解决了谷歌浏览器高版本浏览器88或以上,引用iframe内嵌页面,因为浏览器的安全策略存在跨域,无法使用cookie获取到token信息,导致页面加载不出来的问题,还有其他的解决方案可以在下面给我留言,或者有不懂的地方也可以在下面留言,喜欢的话可以给个关注,会不定时的写一些在开发过程中遇到的一些问题^ - ^

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1239584.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

6.基于蜻蜓优化算法 (DA)优化的VMD参数(DA-VMD)

代码原理 基于蜻蜓优化算法 (Dragonfly Algorithm, DA) 优化的 VMD 参数(DA-VMD)是指使用蜻蜓优化算法对 VMD 方法中的参数进行自动调优和优化。 VMD(Variational Mode Decomposition)是一种信号分解方法,用于将复杂…

ubuntu借助overlay方案实现重启自动还原

配置重启还原OS 首先:sudo apt install overlayroot 安装一下软件 然后编辑配置文件:/etc/overlayroot.conf * overlayroottmpfs or overlayroottmpfs:PARAMETERS write all changes to a temporary (ram only) backing device A tmpfs mount will …

C语言每日一题(35)有效的括号

力扣网 20 有效的括号 题目描述 给定一个只包括 (,),{,},[,] 的字符串 s ,判断字符串是否有效。 有效字符串需满足: 左括号必须用相同类型的右括号闭合。左括号必须以正确的顺序闭合。每个右…

每日一题(LeetCode)----链表--分隔链表

每日一题(LeetCode)----链表–分隔链表 1.题目(86. 分隔链表) 给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。 你应当 保留 两个分区中每个节点的初…

redis运维(十五) 集合

一 集合 ① 概念 集合的元素在redis里面的世界是member集合: setset集合当中不允许重复的元素,而且set集合当中元素是没有顺序的,不存在元素下标 ② sadd、smembers、srem ③ sismember、srandmember、spop、scard spop 命令用于移除集合中的指定 …

数据结构学习笔记——多维数组、矩阵与广义表

目录 一、多维数组(一)数组的定义(二)二维数组(三)多维数组的存储(四)多维数组的下标的相关计算 二、矩阵(一)特殊矩阵和稀疏矩阵(二)…

前端CSS实现响应式TimeLine效果(附源码)

文章目录 纯CSS搭建,先上效果图(附有源码)视图层 index.htmlindex.css 公用样式文件Main.css 主要的样式文件 纯CSS搭建,先上效果图(附有源码) 本效果为纯CSS搭建,适配移动端和PC端&#xff01…

FreeRTOS列表和列表项

FreeRTOS内核调度使用了大量的列表(list)和列表项(listitem)数据结构。它的源码中涉及到很多列表的操作,对于FreeRTOS来说,列表就是它最基础的一部分,列表被用作FreeRTOS调度器使用,…

SQL 中的 MIN 和 MAX 以及常见函数详解及示例演示

SQL MIN() 和 MAX() 函数 SQL中的MIN()函数和MAX()函数用于查找所选列的最小值和最大值,分别。以下是它们的用法和示例: MIN() 函数 MIN()函数返回所选列的最小值。 示例: 查找Products表中的最低价格: SELECT MIN(Price) F…

搜维尔科技:电影中面部动画的演变,Faceware面部捕捉成后起之秀

面部动画是电影中角色表演的一个重要方面,尤其是在严重依赖电子动画、化妆效果和动作捕捉系统的奇幻电影中。在《龙与地下城:盗贼荣耀》电影中,龙裔角色的面部动画是一个复杂的系统,使该生物在大屏幕上栩栩如生。该系统依赖于一种…

【代码随想录】算法训练计划30

【代码随想录】算法训练计划30 1、51. N 皇后 按照国际象棋的规则,皇后可以攻击与之处在同一行或同一列或同一斜线上的棋子。 n 皇后问题 研究的是如何将 n 个皇后放置在 nn 的棋盘上,并且使皇后彼此之间不能相互攻击。 给你一个整数 n ,…

【鸿蒙生态千帆起】HarmonyOS 系统级地图与位置服务,赋能广大开发者

在"与 HarmonyOS 同行,开放生态,共赢未来"为主题的 HUAWEI Developer Day(简称 HDD)沙龙中,Petal Maps 为开发者们带来了在 HarmonyOS 下地图领域的最新技术探索与实践成果。 得益于 HarmonyOS 一次开发多端…

小程序存在优惠卷遍历,但是歪了

进入小程序,因为是一个小商城,所以照例先查看收货地址是否存在越权,以及能否未授权访问,但是发现不存在这些问题,所以去查看优惠卷 进入领券中心,点击领取优惠券时抓包 发现数据包,存在敏感参数…

【java】想要限制每次查询的结果集不能超过10000行,该如何实现?

文章目录 前言 前言 对于一些Saas化软件,当某个租户在执行查询SQL时,如果查询条件出现了BUG,导致去查了所有租户的数据,这种情况是非常严重的,此时就需要在架构层面做限制,禁止一些特殊SQL的执行&#xff…

.Net6使用WebSocket与前端进行通信

1. 创建类WebSocketTest: using System.Net.WebSockets; using System.Text;namespace WebSocket.Demo {public class WebSocketTest{//当前请求实例System.Net.WebSockets.WebSocket socket null;public async Task DoWork(HttpContext ctx){socket await ctx.We…

还记得高中生物书上的莫斯密码吗?利用Python破解摩斯密码的代码示例!

文章目录 前言摩尔斯电码Python实现摩斯密码对照表加密解密测试 完整代码总结关于Python技术储备一、Python所有方向的学习路线二、Python基础学习视频三、精品Python学习书籍四、Python工具包项目源码合集①Python工具包②Python实战案例③Python小游戏源码五、面试资料六、Py…

数学建模之拟合及其代码

发现新天地,欢迎访问Cr不是铬的个人网站 引言 与插值问题不同,在拟合问题中不需要曲线一定经过给定的点。拟合问题的目标是寻求一个函数(曲线),使得该曲线在某种准则下与所有的数据点最为接近,即曲线拟合…

【Docker】Docker安装Nginx配置静态资源

1.下载镜像 2.创建nginx配置文件 3.创建nginx容器运行 4.配置nginx静态资源 1.下载镜像 Dockerhub官网:Docker docker pull nginx docker pull nginx下载最新版本 默认latest 下载指定版本docker pull nginx:xxx 2.创建nginx配置文件 启动容器之前要创建nginx…

数字图像处理(冈萨雷斯)学习笔记

目录 一.机器视觉和计算机视觉二.图像处理基础1.什么是图像2.如何访问图像 三.图像仿射变换四.灰度变换 一.机器视觉和计算机视觉 机器视觉(Machine Vision,MV)和计算机视觉(Computer Vision,CV)的区别和联系: 机器视觉更注重广义图像信号(激光&#xff…

2023 年收入最高的 10 种编程语言 Java 排第 10 位

在过去的一年中(从2022年10月1日到2023年10月1日),DevJobsScanner进行了全球范围内超过1,000万份开发工作机会的分析,以深入了解市场动向、最热门的编程语言以及薪酬最高的趋势。值得注意的是,这项研究的焦点仅集中在美…