CookieContainer在处理域名时存在问题,这会影响客户端浏览器或处理器对cookie的访问控制:
不同域名的Web不能访问其他域名的cookie
子域名可以访问该子域名及其所有父域名的cookie
父域名或域名本身不能访问其任何子域名的cookie
CookieContainer内部结构:
CookieContainer cc has m_domainTable field Hashtable m_domainTable Hashtable Key: string domain Hashtable Value: PathList pathList PathList pathList has m_list field SortedList m_list Key: string path Value: CookieCollection colCookies
CookieContainer有三个关键方法:Add、GetCookies和SetCookies,但它们在处理域名时存在以下问题:
Add(Cookie) vs Add(Uri, Cookie)重载:
Add(Cookie):直接使用cookie的domain属性作为hashtable键存储
Add(Uri, Cookie):使用rfc2109标准,所有域名都以点开头存储
问题本质:Add(Cookie)将.sub.domain.com和sub.domain.com存储在不同组中,但从逻辑上讲,这两个cookie都应该对http://sub.domain.com可见
问题#1:无法检索以点开头的当前子域名cookie和不以点开头的父域名cookie
问题#2:无法检索当前子域名cookie,因为子域名在开头添加了点
private void BugFix_CookieDomain(CookieContainer cookieContainer) { Hashtable table = (Hashtable)_ContainerType.InvokeMember("m_domainTable", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetField | System.Reflection.BindingFlags.Instance, null, cookieContainer, new object[] { }); ArrayList keys = new ArrayList(table.Keys); foreach (string keyObj in keys) { string key = (keyObj as string); if (key[0] == '.') { string newKey = key.Remove(0, 1); table[newKey] = table[keyObj]; } } }
避免使用Add(Cookie):始终使用Add(Uri, Cookie)
及时调用修复函数:每次添加cookie后或使用GetCookies前调用BugFix_CookieDomain函数
系统使用前检查:在系统使用CookieContainer容器前调用修复函数
技术说明:此修复方案假设始终使用Add(Uri, Cookie)方法并且已创建点域名键。更好的编码方式是修改此代码以确保点域名键始终镜像到非点域名键,反之亦然,这样就可以使用Add(Cookie)方法。