zoukankan      html  css  js  c++  java
  • Cookie文件说明及IE的Cookie文件格式

    1、Cookie文件的实质

      Cookie实际上是Web服务端与客户端(典型的是浏览器)交互时彼此传递的一部分内容,内容可以是任意的,但要在允许的长度范围之内。客户端会将它保存在本地机器上(如IE便会保存在本地的一个txt文件中),由客户端程序对其进行管理,过期的Cookie会自动删除。每当客户端访问某个域下某个目录中的网页时,便会将保存在本地并且属于那个域下对应目录的有效Cookie信息附在网页请求的头部信息当中一并发送给服务端。

    2、Cookie文件的保存位置

      不同的客户端,其Cookie的保存方式、保存位置各不相同,这里只说一下Windows系统中IE的Cookie文件保存位置。

      在Windows 2000/XP系统中,Cookie默认保存在C:/Documents and Settings/<username>/Cookies/目录下(此处的<username>为你登录系统时使用的用户名,在开始->运行中输入cookies便可打开该目录),命名规则为<username>@<domain>.txt。

        重点:COOKIE文件名格式为:你的用户名@产生的COOKIE的网页文件所在的WEB目录[COOKIE改变的次数].txt

      与2000/XP不同的是,在Windows 95/98/ME系统中Cookie文件默认是保存在C:/Windows/Cookies/目录下的。

    3、Cookie文件的格式

      IE的Cookie文件实际上就是一个txt文本文件,只不过换行符标记为Unix换行标记(0x0A),由于记事本对Unix换行标记不兼容,打开后内容全在一行看起来不方便,我们可以用EditPlus或UltraEdit-32打开,打开之后,会看到形式如下的内容:
    name
    value
    domain/
    1600
    1263382784
    30020896
    452781968
    30020892
    *
    每一行的内容说明:

    英文说明:
    Line Summary
    1 The Variable Name
    2 The Value for the Variable
    3 The Website of the Cookie’s Owner
    4 Optional Flags
    5 The Most Significant Integer for Expired Time, in FILETIME Format
    6 The Least Significant Integer for Expired Time, in FILETIME Format
    7 The Most Significant Integer for Creation Time, in FILETIME Format
    8 The Least Significant Integer for Creation Time, in FILETIME Format
    9 The Cookie Record Delimiter (a * character)

    中文说明:
    第一行 Cookie变量名
    第二行 Cookie变量值
    第三行 该Cookie变量所属域,形如csdn.net/、blog.csdn.net/或blog.csdn.net/lixianlin/
    第四行 可选标志
    第五行 该Cookie过期时间(FILETIME格式)的高位整数
    第六行 该Cookie过期时间(FILETIME格式)的低位整数
    第七行 该Cookie创建时间(FILETIME格式)的高位整数
    第八行 该Cookie创建时间(FILETIME格式)的低位整数
    第九行 Cookie记录分隔符(为一个星号* )

    补充一下,第三行中Cookie变量所属域,如csdn.net/,它是一个根域,也就是一级域,表示该Cookie变量在该根域下的所有目录中的网页都有效,不管访问该域下的哪个目录中的网页,浏览器都会将该Cookie信息附在网页头部信息当中发送给服务端;blog.csdn.net/,是一个二级域,表示该Cookie只对blog这个二级域下目录中的网页有效;blog.csdn.net/lixianlin/,是一个二级域下的目录,只有访问blog这个二级域下lixianlin这个目录中的网页时,才会把该Cookie信息附在请求头部信息当中发送给服务端。需要指出的是csdn.net/和www.csdn.net/并不相同,前者是根域,后者是一个二级域,只是人们习惯了www这样的形式,所以大多数的网站首页都用http://www.xxx.com/这样的二级域来访问。

    附FILETIME格式定义:
    typedef struct _FILETIME {
        DWORD dwLowDateTime;
        DWORD dwHighDateTime;
    } FILETIME, *PFILETIME, *LPFILETIME;

    1. COOKIE文件格式:

    COOKIE文件为操作系统cookies目录下的一堆txt文件。文件名格式为:
    <用户名>@<域名>[数字].txt
    即,同一个域下可能有多个cookie文件:
    elf@sohu[1].txt
    elf@sohu[2].txt
    elf@sohu[3].txt
    文件名中的数字含义不明。实际上,浏览网页时,浏览器会根据cookies目录下index.dat中的索引信息去定位到某一个文件,然后查找相应COOKIE字段值。

    COOKIE文件为UNIX格式,只有换行(0x0A)没有回车(0x0D)。每个COOKIE文件内,各字段之间以*分隔,每个字段均包含8行信息:

    _ntes_nnid                                  // 字段名

    456f74e9863f8f4b1a1e37774b0c464d,0            // 字段值

    163.com/                                     // 字段所属域

    3584                                            // 标志位

    3205176064                                // 过期时间(低位)

    37425091                                    // 过期时间(高位)

    2444768976                                // 创建时间(低位)

    30082544                                    // 创建时间(高位)


    其中,过期时间和创建时间为FILETIME,需要转成16进制然后拼起来看。标志位标记了一些安全信息,如是否是HTTPONLY(稍后详述)的等等。

    2. WININET API对COOKIE的读写

    非浏览器客户端想要读写COOKIE,有如下几个函数可用:

    InternetGetCookie 
    InternetSetCookie 
    InternetGetCookieEx 
    InternetSetCookieEx 
    具体参数含义可以参考MSDN,有如下几个地方需要注意的:

    1) 上述4个函数的参数lpszCookieName(COOKIE字段名)一般传NULL,而不要按MSDN里说的那样去传一个字段名,否则可能失败。get时,传NULL,会拿到一个类似“name1=value1; name2=value2; ...”这样的字符串,自己去解析一下就好了,但是像标志位、过期时间等信息就丢掉了。set时,传NULL,其它信息(如字段名、值、过期时间)都在lpszCookieData里以固定格式写好传进去:

    view plaincopy to clipboardprint?
    my_name=my_value; path=/; expires=Thu, 07-Mar-13 09:15:47 GMT; domain=.sohu.com; HttpOnly  
    my_name=my_value; path=/; expires=Thu, 07-Mar-13 09:15:47 GMT; domain=.sohu.com; HttpOnly

    注:上面代码中,时间的格式为"day-month-year hour:minute:second"。

    2) 在get时,如果参数lpszURL为1级域名,那么会同时拿到该域名下所有2级域名及子目录下的符合条件的COOKIE。如果参数lpszURL为2级域名,会同时拿到所有子目录下的符合条件的COOKIE。如http://sohu.com,会拿到http://bai.sohu.com下的COOKIE。

    3) VISTA和WIN7,且IE7或IE8时,IE默认开启保护模式,此时IE读写的cookie不是在cookies目录下,而是cookies目录的low目录下。而客户端是从哪个目录下去读取COOKIE,就取决于当前客户端进程的权限:普通权限进程拿cookies目录,受限(LOW)权限拿LOW目录。以PinyinUp.exe为例,因为输入法的进程总是以普通权限启动的,想拿LOW目录下的COOKIE,就需要以低权限启动另外一个进程,用子进程去拿:

    view plaincopy to clipboardprint?
    {   
        HANDLE hProcess = GetCurrentProcess();   
        HANDLE hToken = NULL, hTokenNew = NULL;   
        PSID plntegritySicl = NULL;   
        TOKEN_MANDATORY_LABEL tml = {0};   
        PROCESS_INFORMATION procInfo = {0};   
        STARTUPINFO StartupInfo = {0};   
        ULONG ExitCode = 0;   
           
        if (!ImpersonateSelf(SecurityImpersonation)) {   
            return FALSE;   
        }   
        // 指定低权限:   
        if (!ConvertStringSidToSid(SDDL_ML_LOW, &plntegritySicl)) {   
            return FALSE;   
        }   
        BOOL bRes = FALSE;   
        if (OpenProcessToken(hProcess, MAXIMUM_ALLOWED, &hToken)) {   
            if (DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hTokenNew)) {   
                tml.Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;   
                tml.Label.Sid = plntegritySicl;   
                if (SetTokenInformation(hTokenNew, TokenIntegrityLevel, &tml, sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(plntegritySicl))) {   
                    if (CreateProcessAsUser(hTokenNew, NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &procInfo)) {   
                        bRes = TRUE;   
                    }   
                    if (bWait) {   
                        WaitForSingleObject(procInfo.hProcess, 10 * 1000);   
                    }   
                }   
                CloseHandle(hTokenNew);   
            }   
            CloseHandle(hToken);   
        }   
        return bRes;   
    }  
    {
        HANDLE hProcess = GetCurrentProcess();
        HANDLE hToken = NULL, hTokenNew = NULL;
        PSID plntegritySicl = NULL;
        TOKEN_MANDATORY_LABEL tml = {0};
        PROCESS_INFORMATION procInfo = {0};
        STARTUPINFO StartupInfo = {0};
        ULONG ExitCode = 0;
        
        if (!ImpersonateSelf(SecurityImpersonation)) {
            return FALSE;
        }
        // 指定低权限:
        if (!ConvertStringSidToSid(SDDL_ML_LOW, &plntegritySicl)) {
            return FALSE;
        }
        BOOL bRes = FALSE;
        if (OpenProcessToken(hProcess, MAXIMUM_ALLOWED, &hToken)) {
            if (DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hTokenNew)) {
                tml.Label.Attributes = SE_GROUP_INTEGRITY | SE_GROUP_INTEGRITY_ENABLED;
                tml.Label.Sid = plntegritySicl;
                if (SetTokenInformation(hTokenNew, TokenIntegrityLevel, &tml, sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(plntegritySicl))) {
                    if (CreateProcessAsUser(hTokenNew, NULL, szCmd, NULL, NULL, FALSE, 0, NULL, NULL, &StartupInfo, &procInfo)) {
                        bRes = TRUE;
                    }
                    if (bWait) {
                        WaitForSingleObject(procInfo.hProcess, 10 * 1000);
                    }
                }
                CloseHandle(hTokenNew);
            }
            CloseHandle(hToken);
        }
        return bRes;
    }

    4) 在IE7及以后,cookie引入了一个属性HTTPONLY,值为0x2000。该标志是一个安全性标志,如果一个COOKIE字段具有该属性(标志位具有0x2000这一位),则网页脚本无法获取该字段,此字段只存在于http请求的HEADER中。而对于客户端,则有:
    IE6或IE7环境下:客户端无法通过InternetGetCookie获取此字段值,只能读取COOKIE文本,然后手动解析(参考第一部分:COOKIE文件格式)。
    IE8环境下:客户端可以通过InternetGetCookieEx,且参数dwFlags包含0x2000,来获取此字段值。

  • 相关阅读:
    Windows phone 墓碑机制的一些源码
    关于Image一些比较抽象的东西(Build Type与 同步以及异步加载的差异)
    自定义控件之Button控件的自定义
    Java集合最全解析,学集合,看这篇就够用了!!!
    看完让你彻底搞懂Websocket原理
    别人的前途我不敢决定
    花一年的时间让自己过得像个人样
    开篇
    你看得懂吗?
    反思
  • 原文地址:https://www.cnblogs.com/peijie-tech/p/4000998.html
Copyright © 2011-2022 走看看