本地联调单点登录,iframe跨域cookie丢失
需求:A站点内用iframe
嵌入B站点,需实现单点登录。
问题:我在本地调试时,由于本地开发环境A、B不同域,便手动给本地(嵌入的B站点)添加cookie
,A站点内的B站点能正常自动带上cookie
请求后台接口。
但是,同样代码,在小伙伴那遇到问题,发现iframe
嵌入的B站点请求接口时未带上cookie
。
分析
因为我chrome版本比较低,总会遇到一些兼容问题,大概率是浏览器版本的区别(类似这种跨域遇到的问题,一般是由于浏览器的安全策略)。
搜iframe cookie(丢失)
就出来很多相关解释。
原因
浏览器的Cookie
新增了SameSite
属性(用来防止CSRF攻击
和用户追踪
- 推荐阅读【2】有相关介绍)。chrome 80+
将未声明SameSite
值的Cookie
默认设置为SameSite=Lax Cookie
(大多数情况不发送第三方Cookie
)。
解决方案
参考下面推荐阅读文章,简单列一下几种解决方案:
1、客户端解决方案
通过设置chrome
浏览器相关策略开关,如
-
低于91版本的chrome,disabled这2个flag:
same-site-by-default-cookies
cookies-without-same-site-must-be-secure
-
91及以上,且94以下版本,设置浏览器features(可参考推荐阅读【3】)
--disable-features=SameSiteByDefaultCookies
-
94及以上版本,上述设置都不支持了,即浏览器全面禁止三方
cookie
。PS:客户端解决方案只适用于本地联调,只作用于本地浏览器;而且高版本浏览器现在都不支持了。
因此,针对开头提到的场景,后面B站点可能要采取localStorage
共享cookie
数据,然后在请求头加_cookie
参数请求B站点服务器接口,有服务器再作一层校验。
2、服务器解决方案
https
协议 + SameSite=None
PS:后面有亲测例子
推荐阅读【1】也提到浏览器将全面禁止第三方cookie
,因此,前端跨域cookie
的问题,得换个角度去解决,比如在客户端跨域请求变成非跨域,想办法获取cookie
后存起来用其他方式传输(如【1】的第四个“代理服务”方案)
3、代理服务
思路:先解决跨域,再解决cookie传输问题。
PS:每个应用场景不同,这里只是个人尝试解读【1】第4个代理服务方案的场景
场景:C网站(假设域名C.com
) 请求 D后台服务的登陆校验接口(假设域名D.com
),登陆后需记录其登陆信息cookie
,然后获取用户信息。
流程设计:
- 添加一层C'站点(与C同域),作为代理服务器,把登陆请求先发给C'(基于
iframe+postMessage
跨域); - 中间代理服务器C',再向目标服务器D发起真正的后台请求进行登陆校验,把
response
返回的cookie
同步返回给C'网站; - 需要获取当前登陆的用户信息时,把
cookie
放在请求头的_cookie
参数里请求C'的fetchUser
接口,C'服务器把_cookie
再塞进header
的cookie
里请求D真实的fetchUser
接口;
在这,我有以下疑惑🤔:
- 第1步,为什么用
iframe
的方式去跨域请求C'的接口,为什么不直接C跨域请求C'代理服务的接口(即网站项目http://127.0.0.1:8000
像第3步-查询数据一样,直接请求8001
的/login
是不是也行)? -
如果C站点本身有自己的后台服务,直接作为代理服务器,就不用再考虑C网站跨域请求的
cookie
问题了?如果C站点可控的话,这种方式更方便?欢迎大家戳戳留下脚印,欢迎留言交流哦~
其他相关
亲测服务器解决方案(跨域Set-Cookie
)
浏览器:Chrome版本 102.0.5005.61
A)网站web parent
(http://127.0.0.1:5501/index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>web parent</title>
</head>
<body>
web parent
<iframe src="http://localhost:5502/index.html"></iframe>
</body>
</html>
B)网站web sub
(http://localhost:5502/index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>web sub</title>
<script src="https://cdnjs.gtimg.com/cdnjs/libs/zepto/1.1.4/zepto.js"></script>
</head>
<body>
web sub
<script type="text/javascript">
console.log('web sub', '1 document.cookie', document.cookie);
var addCookie = function (name, value, time) {
var strSec = time;
var exp = new Date();
exp.setTime(exp.getTime() + strSec * 1);
document.cookie = name + "=" + value + ";expires=" + exp.toGMTString() ;// + ";SameSite=None;Secure";
}
console.log('set cookie', 'web_sub_cookie', 'I_AM_SUB_COOKIE');
addCookie('web_sub_cookie', 'I_AM_SUB_COOKIE',600000);
console.log('web sub', '2 document.cookie', document.cookie);
</script>
</body>
</html>
- 单独访问网站web sub时,可看到cookie设置成功
- 但新标签页打开网站web parent时,却访问不到该cookie,也设置不了cookie
- 设置cookie时加上'SameSite=None;Secure'会设置不成功
C)添加网站web sub的服务器接口
(http://localhost:5503/setCookie)
// 1、加载模块
const http = require('http');
// 2、创建http
var server = http.createServer(); // 创建一个web容器 静态服务器
// 3、监听请求事件
server.on('request', function (request, response) {
// 监听到请求之后所做的操作
var url = request.url;
if (url === '/setCookie') {
response.writeHead(200, {
'Content-Type': 'application/json',
'Set-Cookie': ['web_sub_service_cookie=I_AM_WEB_SUB_SERVICE_COOKIE;']
});
response.end(JSON.stringify({}));
}
})
// 4、监听端口,开启服务
server.listen(5503, function () {
console.log("服务器已经启动,可访问以下地址:");
console.log('http://localhost:5503');
})
启动上述node服务,在web parent站点用iframe
引用web sub站点服务器接口
<iframe src="http://localhost:5503/setCookie"></iframe>
web sub站点服务器response
里set-cookie
是默认被禁用的
加上SameSite
和Secure
就可以
'Set-Cookie': ['web_sub_service_cookie=I_AM_WEB_SUB_SERVICE_COOKIE;SameSite=None;Secure'],
这个cookie
如上设置属性之后,跨域下可设置、读取。(在chrome 102
版本上测试ok)
在文章【4】里提到:
Chrome
也宣布,将在下个版本也就是Chrome 83
版本,在访客模式下禁用三方Cookie
,在2022
年全面禁用三方Cookie
,到时候,即使你能指定SameSite
为None
也没有意义,因为你已经无法写入第三方Cookie
了。
目前亲测还能用,应该在不久后就会全面禁用的。
转载来自:https://segmentfault.com/a/1190000041959550
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库