CSS / JavaScript / hacking:检测:在链接上访问的样式*不需要*直接检查或者比我快
这是在http://cssfingerprint.com的研究目的
考虑下面的代码:
<style>
div.csshistory a { display: none; color: #00ff00;}
div.csshistory a:visited { display: inline; color: #ff0000;}
</style>
<div id="batch" class="csshistory">
<a id="1" href="http://foo.com">anything you want here</a>
<a id="2" href="http://bar.com">anything you want here</a>
[etc * ~2000]
</div>
我的目标是检测foo是否使用:visited样式呈现。
我想检测foo.com是否被访问,而不直接查看$('1').getComputedStyle
(或者在Internet Explorer中, currentStyle
)或者该元素上的任何其他直接方法。
这样做的目的是为了避免潜在浏览器限制,阻止直接检查访问链接的样式。
例如,也许你可以在<a>
标签中放置一个子元素,或直接检查文本的样式; 等等。任何不直接或间接依赖$('1').anything
都是可以接受的。 对孩子或父母做一些聪明的事情可能是必要的。
请注意,仅出于此目的,情景是浏览器将对JavaScript的所有<a>
元素的属性(而不是其他)进行撒谎,并且它只会呈现color:
in :visited
。 因此,依赖于文本大小或background-image
将不能满足此要求。
我想提高我目前的抓取方法的速度。
大多数情况下(至少在Firefox中使用jQuery方法)花费在document.body.appendChild(batch)
,因此找到一种方法来改善这种调用可能是最有效的。
有关当前速度测试结果,请参阅http://cssfingerprint.com/about和http://cssfingerprint.com/results。
我正在使用的方法可以在http://github.com/saizai/cssfingerprint/blob/master/public/javascripts/history_scrape.js上看到
总结tl; dr,他们是:
getComputedStyle
检查每一个 <a>
标签内,并使用jQuery的可见选择器,只提取可见文本(=访问过的链接ID) FWIW,我是一顶白帽子,我正在与EFF和其他一些相当知名的安全研究人员进行磋商。
如果您提供了一种新的方法或加速方法,那么您会在http://cssfingerprint.com/about(如果您想成为:-P)以及未来发表的论文中获得感谢。
ETA:赏金只会因为建议而得到回报
如果有多个建议符合任何一个标准,那么最能胜出的建议。
ETA 2:我添加了两种先前最好的测试方法(reuse_noinsert,最好在Firefox / Mozilla上,以及mass_insert,它非常接近的竞争对手)的基于宽度的变体。 请访问http://cssfingerprint.com几次从不同的浏览器; 我会自动获得速度测试结果,所以我们会发现它是否比以前的方法更好,如果是的话多少。 谢谢!
ETA 3:目前的测试表明,在Chrome中使用offsetWidth
(而不是getCalculatedStyle
/ currentStyle
)约为2ms(1.8%),在Firefox中约为24ms(4.3%),这并不是我想要获得固定奖励的10%赢得。 有一个想法如何克服剩下的10%?
[新更新]
如果你想要结果只是视觉呈现,那么最快的方法是使用CSS计数器..
CSS:
body{
counter-reset: visited_counter;
}
a:visited{
counter-increment: visited_counter;
}
#results:before{
content:counter(visited_counter);
}
这会在id为'results'的元素之前添加访问过的链接的数量。
不幸的是,没有办法从JavaScript访问它,你只能显示它..
[初始答案]
你知道jQuery直接支持:visited
选择器吗?
像$('a:visited')
[更新]
作为替代方案,您可以应用不依赖于getComputedStyle
的CSS属性来检索..
像a:visited{height:1px;display:block;}
然后检查offsetHeight
。
color : inherit
警告:afaik它不会在lte ie7上运行
对于iete7必须
visibility : hidden
在a:visited
和visibility : inherit
了子级 一个类似的想法,但回避.getComputedStyle()
:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<title></title>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<style type="text/css">
a:visited { display: inline-block; font-family: monospace; }
body { font-family: sans-serif; }
</style>
<script type="text/javascript">
function test() {
var visited = document.getElementById("v").childNodes[1].firstChild.clientWidth;
var unvisited = document.getElementById("u").childNodes[1].firstChild.clientWidth;
var rows = document.getElementsByTagName("tr");
for (var i = 1, length = rows.length; i < length; i++) {
var row = rows[i];
var link = row.childNodes[1].firstChild;
var width = link.clientWidth;
row.firstChild.appendChild(document.createTextNode(link.href));
row.childNodes[2].appendChild(document.createTextNode(width === visited ? "yes" : (width === unvisited ? "no" : "unknown")));
}
}
</script>
</head>
<body onload="test()">
<table>
<tr><th>url</th><th>link</th><th>visited?</th></tr>
<tr id="u"><td></td><td><a href="http://invalid_host..mplx/">l</a></td><td></td>
<tr id="v"><td></td><td><a href="css-snoop.html">l</a></td><td></td>
<tr><td></td><td><a href="http://stackoverflow.com/">l</a></td><td></td>
<tr><td></td><td><a href="http://www.dell.com/">l</a></td><td></td>
</table>
</body>
</html>
当然,这个技巧是确保访问和未访问的链接具有不同的宽度(在这里,通过使用sans-serf与等宽字体)并将它们设置为inline-block
以便可以通过clientWidth
访问它们的宽度。 经测试可用于FF3.6,IE7,Chrome 4和Opera 10。
在我的测试中,访问clientWidth
始终比依赖计算样式的任何东西都快(有时高达40%,但clientWidth
很大)。
(哦,并为<body onload="...">
废话道歉;我试图在没有框架的情况下在IE中执行事件已经太长了,而且我厌倦了与它作斗争。)
下一篇: Flight request returning 406 error code on PUT / DELETE