Learning to be Giant.

CSS :visited pseudo-class and privacy

|
a:visited:after{
    content: '(Visited)';
}

我想做一个当链接被访问之后链接文字会被追加一个(Visited)的效果,提示用户该链接已经被点击过了。

但是这个代码它失效了。

经过查询,发现了MDN上的这个文章:Privacy and the :visited selector。原因是:visited指定的样式配合getComputedStyle()方法就可以获得用户的访问历史,从而侵犯隐私。Mozilla的做法是使得:visited当中的大部分的属性失效,除了:

  1. color
  2. background-color
  3. border-color (and its sub-properties)
  4. outline-color
  5. The color parts of the fill and stroke properties

并且:

getComputedStyle() and similar functions such as element.querySelector() always return values indicating that a user has never visited any of the links on a page.

有意思的问题就来了:那么为什么只有像color之类的属性被允许,其他的就不被允许呢?在Preventing attacks on a user’s history through CSS :visited selectors我们可以找到答案:

  1. They can make visited and unvisited links take up different amounts of space, and then determine whether the link is visited from the positions of other elements on the page.
  2. They can make visited and unvisited links cause different images to load.
  3. They can use CSS features such that matching selectors, doing layout, or doing painting would take a different amount of time depending on whether the link is visited or unvisited, and then run a performance test.

如果认为上面的解释不够详细,在Plugging the CSS History Leak对于这个问题给出了更加详细的三种攻击方式,包括:

  1. Layout-Based Attacks 通过更改visited链接的layout,使得其周围元素的位置属性发生改变,从而可以获知是否访问过该链接;或者通过设置不同background-image的方法,从服务器load不同的图片,从而获知链接是否被访问。
  2. Some Timing Attacks 通过visitedunvisited元素选择的时候的时间差异来达到检测的目的。
  3. Computed Style Attacks 通过调用getComputedStyle()方法来检测属性变化达到检测的目的。

由于以上的种种问题,最终的结果就是在大多数情况下,:visited会被当做没有访问过看待的。

由于理解比较粗浅,可能有疏漏和错误的地方,如果发现请指出,共同学习。

Disclaimer: This is a personal weblog. The opinions expressed here represent my own and not those of any entity with which I have been, am now, or will be affiliated.

Comments