找回密码
 会员注册
查看: 12|回复: 0

深入理解WKWebView(基础篇)——聊聊cookie管理那些事

[复制链接]

1

主题

0

回帖

4

积分

新手上路

积分
4
发表于 2024-10-8 15:35:12 | 显示全部楼层 |阅读模式
1. 前言在浏览内核加载网络资源的过程中我们离不开 ?HTTP 协议。它是在 Web 上进行数据交换的基础,同时也是一种无状态的 client-server 协议。这种无状态的属性促使许多端存储技术产生,其中最重要的技术之一就是 cookie 存储技术,它能方便的将数据存储于客户端,且在每次请求中都会在请求头中携带 cookie 数据并发送给 server。cookie 技术的便捷性使得它在多种场景中被广泛使用,有时候甚至存在滥用情况,对同一 cookie 实例,前端、客户端、服务端都可以轻易的进行增删改查,我们在享受其便捷性的同时,也有必要确保其被正确、可控的使用。本文将在前系列文章的基础上,继续深入 WKWebView 源码,聊聊 cookie 管理那些事,希望给大家带来一些新的视角和认知,揭开 cookie 管理的迷雾。2. Cookie 概述MDN官网(https://developer.mozilla.org/en-US/docs/Web/HTTP/Cookies)对cookie的介绍如下:HTTP cookie(也叫 Web cookie 或浏览器 cookie)是保存在浏览器本地的一小块数据,它会在浏览器向服务器发起请求时被携带并发送到服务器上。通常,它用于告知服务端两个请求是否来自同一浏览器,如保持用户的登录状态。cookie 使基于无状态的?HTTP?协议记录稳定的状态信息成为了可能。cookie 主要用于以下三个方面:会话状态管理:如用户登录状态、购物车、游戏分数或其它需要记录的信息。个性化设置:如用户自定义设置、主题等。浏览器行为跟踪:如跟踪分析用户行为等。简单介绍完 cookie的概念后,接下来我们再分别从前端、后端、客户端的视角聊聊 cookie 的基本使用。3.?Cookie 基本使用丨3.1?前端通过 js 操作 cookie详细 cookie 格式语法参考 MDN 语法链接:https://developer.mozilla.org/zh-CN/docs/Web/API/Document/cookie//?读取所有可从当前页面访问的?cookieallCookies?=?document.cookie;//?写一个新?cookiedocument.cookie?=?"someCookieName=true;?expires=Fri,?31?Dec?9999?23:59:59?GMT;?path=/";丨3.2?后端配置 cookie详细 cookie 格式语法参考 MDN 语法链接:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Cookies在 response header 中返回需要种到端上的 cookie ,我们通过 Charles 工具抓包可以看到 header 中如下信息:丨3.3?客户端操作 cookieiOS 系统在?WKHTTPCookieStorage?类中提供如下 API 进行 cookie?操作:@interface WKHTTPCookieStore : NSObject/*!?@abstract?获取所有?cookie?@param?completionHandler?获取所有?cookie?后回调?*/-?(void)getAllCookiesvoid?(^)(NSArray?*))completionHandler;/*! @abstract 设置一个 cookie @param cookie 需要设置的 cookie @param completionHandler cookie 设置成功的回调 */ -?(void)setCookieNSHTTPCookie?*)cookie?completionHandlernullable?void?(^)(void))completionHandler;/*! @abstract 删除指定的 cookie @param completionHandler cookie 成功删除的回调 */ -?(void)deleteCookieNSHTTPCookie?*)cookie?completionHandlernullable?void?(^)(void))completionHandler;@end可以看到,不同场景下的 cookie 操作都是极其简单的,我们似乎已经通过简单的封装接口掌握了 cookie 技术,那么问题来了:(1)cookie 究竟是存储在哪的?内存,还是磁盘?(2)三种不同场景的 cookie 操作是如何协同工作的?现在,我们能回答这些问题吗?如果不能,请继续跟随我深入 WKWebView 源码,让代码告诉我们答案。4.?WebKit?Cookie 技术原理再次回到源码探索的道路,现在我们再回顾一下在《深入理解 WKWebView(入门篇)—— WebKit 源码调试与分析》提及的源码探索的核心技巧:紧紧围绕?UIProcess、WebContent、NetworkProcess 三大进程进行理解。丨4.1?三大进程与三种场景如上图所示,我们将 cookie 操作的三种场景与三大进程进行关联,其中,(1)客户端操作在 UIProcess 进程(即我们的 app 进程),通过封装的 WKHTTPCookieStorage 进行操作。(2)前端 js 函数,通过 JSCore 解析执行后最终调用了 WebContent 进程中的 C++ 函数进行操作,如下所示:virtual?String?cookies(Document&,?const?URL&)?const;virtual?void?setCookies(Document&,?const?URL&,?const?String&?cookieString);(3)WKWebView 中的网络请求最终都是通过 NetworkProcess 中的 NSURLSession 管理的,服务端网络响应的 cookie 设置操作都在该进程中完成。丨4.2?三种场景下的协同工作cookie 管理协同图如图所示,描述了三大场景下 cookie 的协同管理,接下来,我们将结合该图解答第二小节中提出的问题。问题一:cookie 究竟是存储在哪的?内存,还是磁盘?UIProcess:UIProcess 进程为 app 进程(app 进程中其实有 NSHTTPCookieStorage 仓储进行 cookie 管理,但这不是本文的重点,因此不展开来讲),苹果系统为开发者提供了 WKHTTPCookieStorage API 进行 WebKit?内核的 cookie 管理,WKHTTPCookieStorage 其实并不提供实际的存储能力,而是封装了一系列基于进程间通信的方法,将 UIProcess 进程中发生的 cookie 操作,发送到 NetworkProcess 进程中进行处理,并将执行结果通过回调函数返回。WebContent:WebContent 进程是前端操作 cookie 的进程,原则上,每一个网页页面都只能操作当前页面域名下的cookie。因此基于性能考虑,每一个 WebContent 进程中会有一个 cookieCache 实例,它是 NetworkProcess 进程中存储 cookie 的子集,仅存储当前页面域名下的 cookie,因此 cookieCache 采取了内存缓存的方式,其特征是存储量小,查找速度快。NetworkProcess:NSHTTPCookieStorage setCookie 流程图NetworkProcess 进程是?cookie 存储的最核心进程,它管理来自网络中服务端 response 中配置的 cookie,同时也接受来自前端和客户端的 cookie 操作,是最全的 cookie 存储中心。通过源码分析,我们发现其内部还是通过 NSHTTPCookieStorage 进行管理的,?NSHTTPCookieStorage?有如下存储规则:(1)allCookies:所有 cookie 都会存入字典 allCookies 中,方便快速查询。当我们杀死 app 后,位于内存中的 allCookies 字典也会一同清理掉。(2)sessionOnly false cookie:对于某个 cookie,如果其属性中 sessionOnly 为 false,且设置的过期时间未到达,那我们判断该 cookie?是否具备持久性的逻辑如下:let?persistable?=?self.allCookies.filter?{?(_,?value)?in????????????value.expiresDate?!=?nil?&????????????value.isSessionOnly?==?false?&????????????value.expiresDate!.timeIntervalSinceNow?>?0 }(3)持久性 cookie:具备持久性的 cookie 需要存储到磁盘文件中。存入路径规则如下:let?bundlePath?=?Bundle.main.bundlePathvar?bundleName?=?bundlePath.components(separatedBy:?"/").last!if?let?range?=?bundleName.range(of:?".",?options:?.backwards,?range:?nil,?locale:?nil)?{????bundleName?=?String(bundleName[..
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-9 20:28 , Processed in 0.870597 second(s), 26 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表