📘 第六章 HTTP首部
📄 一句话概括

P3P 是一段机器可读的隐私声明,用缩略标签描述「我收集什么、给谁用」。 它当年只有 IE 认真实现,2018 年前后各家停止支持,现在纯属历史遗迹。

📝 本节和前面几节的关系

上一节的 DNT 是「客户端求你别跟踪」,这一节是「服务端声明自己怎么用数据」。 一个请求、一个响应,两个都没能成事。

一、格式是一串缩略标签

P3P: CP="NOI DSP COR CURa ADMa DEVa TAIa OUR BUS IND",CP 后面是引号包起来的一串词,空格分隔。 每个词都是词典里的缩写:NOI 不标识个人身份,CURa 用于定制,ADMa 用于广告投放, OUR 只给自己用,BUS 会给商业伙伴,IND 表示会用于个体分析。 Demo 里四种声明:10 个标签的响应 166 字节,单个标签的 126,CP="ALL" 也是 126, 空声明 123。

二、它想做什么

思路是:站点在响应里声明自己的数据用法,浏览器拿它跟用户设定的偏好比对, 不一致就弹窗或者拒收 cookie。这样用户不用读隐私政策,机器替他判断。 听起来很合理,但它有三个致命伤,而且一个比一个难修。 第一,声明由站点自己写,没人核对真假。CP="ALL" 一行就能全放行,承诺成了装饰。 Demo 里那两个 126 字节的响应,一个写满了标签,一个只写 ALL,长度一样——但含义天差地别, 而机器没法分辨谁在撒谎。 第二,只覆盖 cookie。后来的 localStorage、浏览器指纹、第三方脚本,它一概管不了。 第三,实现太单一。除了 IE,几乎没有浏览器认真做过比对逻辑,而 IE 退场之后,这段历史就结束了。

三、为什么还值得看

它提供了一个反面教材:想靠「自我声明」解决隐私问题,前提是有人验证。 没有验证,声明就只是格式正确的字符串。 现在的 GDPR 走的是另一条路:不是声明,是责任——违反要罚款,用户有投诉渠道。 约束来自外部,不是来自一行首部。 技术上则是浏览器直接动手:默认拦第三方 cookie、限制跨站存储,不指望站点自觉。

四、动手 Demo:四种 CP 声明,量字节、数标签

同一个页面配四种 P3P 声明:十个标签的完整版、只有一个标签的精简版、CP="ALL" 的万能版、 以及空声明。量出标签数和整条响应字节数。

def parse(cp):
    v = cp.split(u'CP=', 1)[1].strip(u'"')
    return [t for t in v.split() if t]

def make(cp):
    def fn(raw, st):
        return X.reply(u'HTTP/1.1 200 OK',
                       [(u'Content-Type', u'text/html; charset=utf-8'),
                        (u'P3P', cp)], PAGE)
    return fn

实跑输出:

--------------------------------------------------------------------
P3P:一段机器可读的隐私声明
--------------------------------------------------------------------
  声明                                                 标签数   整条响应
  CP="NOI DSP COR CURa ADMa DEVa TAIa OUR BUS IND"     10       166
    不标识个人身份、可定制、可联系、有广告、有第三方
  CP="NOI"                                             1        126
    只声明最基础的一条
  CP="ALL"                                             1        126
    什么都允许(等于没有约束)
  CP=""                                                0        123
    空声明

  这些标签是缩写词典里的词:`NOI` 不标识身份,`CURa` 用于定制,
  `ADMa` 用于广告投放,`OUR` 只给自己用,`BUS` 会给商业伙伴。
  浏览器(当年只有 IE 认真做)拿它跟用户设定的偏好比对,
  不一致就弹窗或者拒收 cookie。

  问题在于:声明是站点自己写的,没人核对真假。
  写个 `CP="ALL"` 就能一路放行,等于把承诺当装饰。
  加上它只覆盖 cookie,管不了后来的 localStorage、指纹、
  跨站脚本——于是 2018 年前后主流浏览器陆续停止支持,
  W3C 也把这个工作组关了。

  今天看到 `P3P` 首部,基本可以判断这是个有年头的老站点。
  它不带来任何保护,只多了几十字节,现代审计一般建议直接删掉。

四种声明对应的标签数是 10、1、1、0,响应大小是 166、126、126、123 字节。 值得盯的是那两个 126:一个是 CP="NOI"(只声明最基础的一条), 一个是 CP="ALL"(等于什么都允许)。字节数一样,含义正相反。 这就是 P3P 的死穴:格式正确不等于内容可信。机器能解析标签,但没法验证站点是不是真的按标签做。 空声明那行 123 字节,比不发多一点点,比完整版少 43 字节——这 43 字节买到的是一段没人读的承诺。

30 秒实验

  1. 给 CP="ALL" 加上更多标签,看字节数怎么变、含义变不变。
  2. 查一查当年 IE 的默认隐私设置是哪一档。
  3. 想一想:现在的「隐私政策弹窗」和 P3P 相比,进步在哪、退步在哪?

常见误区

  1. 「P3P 是现行标准」——2018 年前后主流浏览器已停止支持。
  2. 「写了 P3P 就证明站点合规」——自己声明,没人核对。
  3. 「它管所有数据收集」——只覆盖 cookie。
自测三问(点开对答案) 1. `CP="ALL"` 是什么含义? —— 什么都允许,等于没有约束;它和只写一个标签的声明字节数可能一样。 2. P3P 的三个致命伤是什么? —— 自称自证没人核对、只覆盖 cookie、除 IE 外实现太少。 3. 现在解决隐私问题靠什么? —— 法规(责任与处罚)加浏览器侧的技术限制,不是自我声明。

第六章到这里收尾。下一章换方向:从「报文长什么样」转到「怎么把报文锁进保险箱」——HTTPS。

相关笔记