本帖最后由 junkboy 于 2017-7-4 22:42 编辑
[RFC 6265] 浅谈Cookie:真正意义上的Cookie合并更新
大家想必对 网页_Cookie合并更新 这条命令相当熟悉,但实际上这是条不严谨的命令。HTTP请求时,Cookie是有域、路径以及其它一些参数的区别的。如果你经验足够多,你就知道在一些跨域请求或者一个网站的不同域下有相同的Cookie键的时候,或者网站严格检测跨域请求的时候,就需要自己额外写不少代码来管理Cookie,并且在Cookie的存储和导入上面就有不方便的地方。
有些人可能想问有哪些网站是这样的,我举个例子,钱宝,初学者可以自己去实现一下不同域的功能,你会发现你需要不停地更新每个域的Cookie,除非你全部存储下来,凭添很多代码。
本文以及代码就是针对这些情况,尝试实现自动化Cookie管理方案,像真正的浏览器一样去管理Cookie(当然,浏览器用的是文件)。
先老规矩,提供最新的权威文档,大家一起看一下Cookie的详细定义以及各个参数的意义。
文档标题:[RFC 6265] HTTP State Management Mechanism
文档链接:https://tools.ietf.org/html/rfc6265
重要部分:https://tools.ietf.org/html/rfc6265#page-17
一、定义
Cookie是服务器给浏览器的一段数据,作用有识别用户身份和记录历史,咱们平时的需求自然就是前者。
二、Set-Cookie
结合例子来一一介绍
Set-Cookie: Session=xxxx; Expires=Wed, 04-Jul-18 04:13:38 GMT; domain=.test.com; path=/folder1/; Max-Age=9999; HttpOnly; Secure
Cookie-Name:Cookie的名字
就是例子中的 Session 。
那么这儿有一个疑问:是否大小写敏感呢?
答案是看情况,asp中大小写不敏感,js中大小写敏感。
所以为了兼容,只需要保持大小写敏感即可。
Cookie-Value:Cookie的值
就是例子中的 xxxx 。
有一些特例,例如
当值为 deleted (大小写不敏感)时,删除这个Cookie。
同样,当值为空时,我们也可以删除这个Cookie。
Expires:过期时间,大小写不敏感
这是所谓的GMT时间,也是网络上最常见的时间格式,windows也提供了很多个API供转换。
目前的方案中没有考虑这个,也可以继续完善来考虑它,不过我个人觉得没什么意义。
Max-Age:最大寿命,大小写不敏感
单位是秒,优先级比Expires高。
HttpOnly:大小写不敏感
js无法获取到
Secure:大小写不敏感
只允许https://的请求获取这个Cookie,http://就无法获取到。
domain:域,大小写不敏感
经常会看见域用.开始,这儿要注意,新规范里注明了,这个.已经没有意义,直接删除即可。
path:路径,大小写不敏感
路径
三、Get-Cookie:
首先一个请求的链接,以 WinHttpCrackUrl 为例,解析出了我们需要的:
Scheme:也就是 http:// 还是 https://
Host:域
UrlPath:目录,但是和Path有一定区别,参考代码中的_Path_Format方法
Host和Path决定了取哪些路径的Cookie,Scheme则决定了取这些Cookie中的哪些Cookie。
四、设计
同样源自群里的吹比,第一个版本尝试用哈希表,但是结构很难设计,在dalao的建议下又改用Json。
Cookie在内存中的结构图:
设计管理方案,自然躲不过增删改查。
增和改,也就是代码中的Add方法,遵循的规则如下:
如果路径不是根路径的话,则先增或改本域的本路径,并且删除本域的所有子路径的该Cookie;
如果路径是根路径的话,则先增或改本域的本路径,并且删除本域的所有子路径的该Cookie,并且删除所有本域的子域的根路径的本Cookie。
删:也就是代码中的Del方法,遵循如下规则:
如果指定了cookie的Name,则只删除对应路径下的该Cookie;
如果Path为空,则删除指定的域以及该域的所有子域;
如果CookieName为空,则删除该路径以及该域的所有子路径。
查:也就是代码中的Get方法
由于设计好了Add和Del的规则,Get就变得相对简单了。
五、示范
代码演示了qq.com的不同域的Cookie管理,Json代码来自zyJson,简单整合了一个winhttp请求的类,部分代码copy自鱼刺(和鱼刺本人的讨论也受益匪浅,感谢),也有一些自己的特点:
1、Cookie管理全部托管给自制的Cookie类;
2、Header管理全部交给HashMap;
这样就不再频繁调用WinHttpAddRequestHeaders,而是在WinHttpSendRequest处统一发送。
六、不足
首先是效率,效率肯定是比不上数组循环替换的,但是这个牺牲我个人还是可以接受的,看各位对于跨域请求Cookie管理的需求了。
其次是兼容上,HTTP协yi我觉得是个很灵活的协yi,允许很多自定义的东西,RFC 6265上对于Cookie的规定和讲解也是相当笼统,让人很困惑。怎么说呢?我觉得不同语言不同库可能都有自己的一套处理习惯,造成了大体一致但在一些细节方面比较混乱。
在下抛个砖,只是个雏形,更多在于交流和分享自己的学习思路,未来会继续学习完善,如有谬误,还望指正。
也希望有能力的朋友继续优化或者自己实现个Cookie管理的方案。
下面是代码以及文档,代码中注释还是很清晰的,谢谢阅读。
Cookie类.zip
(187.03 KB, 下载次数: 375)
|