[{"data":1,"prerenderedAt":147},["ShallowReactive",2],{"\u002Fposts\u002Fweb-features-and-privacy":3,"surround:\u002Fposts\u002Fweb-features-and-privacy":138},{"id":4,"title":5,"body":6,"createdAt":130,"description":16,"extension":131,"meta":132,"navigation":133,"path":134,"seo":135,"stem":136,"__hash__":137},"posts\u002Fposts\u002F2023\u002Fweb-features-and-privacy.md","为了保护隐私，Web 标准牺牲了什么？",{"type":7,"value":8,"toc":123},"minimark",[9,13,17,27,33,52,64,81,85,88,96,99,102,109,120],[10,11,5],"h1",{"id":12},"为了保护隐私web-标准牺牲了什么",[14,15,16],"p",{},"隐私保护看起来近些年变得热门，其实在 Web 标准的历史上还是为了隐私做了不少考量，甚至付出代价。这里举两个例子：",[18,19,21,22,26],"h2",{"id":20},"pseudo-class-visited","关于 ",[23,24,25],"code",{},":visited"," 伪类",[14,28,29,30,32],{},"这个伪类能够被大家知道可能很大程度上归功于浏览器的默认样式：IE 和它的继承者们都会默认将蓝色的超链接在访问后标记成紫色；有的网站则可能会自定义访问过的链接颜色，这似乎就是 ",[23,31,25],{}," 的唯一使用场景了。",[14,34,35,36,39,40,43,44,47,48,51],{},"后来我们有了 ",[23,37,38],{},"querySelector"," 和 ",[23,41,42],{},"querySelectorAll","。可以试试看，在任何一个页面点击一个链接，再在控制台调用 ",[23,45,46],{},"document.querySelector(':visited')","，结果返回的依然是 ",[23,49,50],{},"null","，这是为什么呢？",[14,53,54,55,57,58,60,61,63],{},"假设我们创建了一个博客网站，并且引用了【分享到 QQ 空间】的 JS SDK。如果 JS SDK 内部包含了类似于查询 ",[23,56,25],{}," 元素的代码，显然，用户的访问记录将全部被 JS SDK 获取到；甚至 SDK 也可以创建一个透明的包含常见网站链接的容器，它甚至能够知道我们访问过哪些其他网站！为了阻止类似的事情发生，浏览器“欺骗”了 ",[23,59,38],{},"，让它无法得知 ",[23,62,25],{}," 的存在。",[14,65,66,67,69,70,73,74,76,77,80],{},"同样的道理，能够通过 ",[23,68,25],{}," 覆盖的样式也是有限的，例如 ",[23,71,72],{},"color"," 等寥寥数个而已。考虑一下假设我们能够用 ",[23,75,25],{}," 声明 ",[23,78,79],{},"line-height","，那么第三方脚本将能够通过链接列表 -> 创建隐藏元素 -> 计算高度的方式间接知道这些链接是否被访问，从而达到和之前一样的获取隐私的效果。",[18,82,84],{"id":83},"browser-cache","关于浏览器缓存",[14,86,87],{},"如果你做过性能优化，你是否想过，在浏览器缓存一个资源之后，这个资源在其他网站访问时也会被缓存吗？",[14,89,90,91,95],{},"答案",[92,93,94],"strong",{},"曾经","是肯定的。这似乎很符合直觉，因为全局缓存看起来没有什么问题，甚至如果我们大量使用了公共 CDN，这些来自 CDN 的模块就能够提前在其他的网站被加载了。",[14,97,98],{},"但是！缓存本身也可能被作为用户的标识使用，你能想到是什么吗？",[14,100,101],{},"……",[14,103,104,105,108],{},"没错，就是 ",[23,106,107],{},"ETag","。",[14,110,111,112,115,116,119],{},"假设浏览器拥有一个全局缓存的策略（事实上曾经也是这样的），仍然以 QQ 空间 SDK 为例，SDK 可以请求一个资源，比方说是一个 GIF 吧。GIF 的服务端可以让这个资源总是使用协商缓存（",[23,113,114],{},"no-cache","），并且为其下发一个类似于 Web ID 的 ETag。于是，如果另一个网站也引用了 QQ 空间 SDK，那么 QQ 空间就能通过这些网站请求时的 ",[23,117,118],{},"If-None-Match"," 得知这些请求都来自于同一个用户了。",[14,121,122],{},"你可能会觉得这个过程好熟悉——没错，这其实就是“第三方 Cookie”。在各大浏览器绞尽脑汁禁止第三方 Cookie 的今天，缓存也最终被限制为仅在同源站点内生效，通过牺牲可能微不足道的一点加载性能来换取更好的隐私保护。",{"title":124,"searchDepth":125,"depth":125,"links":126},"",2,[127,129],{"id":20,"depth":125,"text":128},"关于 :visited 伪类",{"id":83,"depth":125,"text":84},"2023-11-21","md",{},true,"\u002Fposts\u002Fweb-features-and-privacy",{"title":5,"description":16},"posts\u002F2023\u002Fweb-features-and-privacy","pk-CWUNmLotzBQy_kDbiCOKVPvC6nHBiK9AgWgRyt2U",[139,143],{"title":140,"path":141,"stem":142,"children":-1},"什么？不同函数的 prototype 竟然会表现不同？","\u002Fposts\u002Fdifferent-prototypes","posts\u002F2022\u002Fdifferent-prototypes",{"title":144,"path":145,"stem":146,"children":-1},"如何实现监听 CSS 变量？","\u002Fposts\u002Fobserve-css-vars","posts\u002F2024\u002Fobserve-css-vars",1792500630763]