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检查每一个
  • 把链接的ID(加一个空格)放在<a>标签内,并使用jQuery的可见选择器,只提取可见文本(=访问过的链接ID)
  • FWIW,我是一顶白帽子,我正在与EFF和其他一些相当知名的安全研究人员进行磋商。

    如果您提供了一种新的方法或加速方法,那么您会在http://cssfingerprint.com/about(如果您想成为:-P)以及未来发表的论文中获得感谢。

    ETA:赏金只会因为建议而得到回报

  • 可以在Firefox上避免上面第1点中描述的假设限制,或者
  • 在我拥有足够的当前数据的任何浏览器上执行速度至少快10%,而不是我在http://cssfingerprint.com/about中列出的最佳执行方法
  • 如果有多个建议符合任何一个标准,那么最能胜出的建议。

    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
  • 检测孩子的颜色(JS)
  • 警告:afaik它不会在lte ie7上运行

    对于iete7必须

  • 添加visibility : hiddena:visitedvisibility : inherit了子级
  • 使用javascript检查孩子的可见度(hidden = visited)

  • 一个类似的想法,但回避.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中执行事件已经太长了,而且我厌倦了与它作斗争。)

    链接地址: http://www.djcxy.com/p/41123.html

    上一篇: CSS/JavaScript/hacking: Detect :visited styling on a link *without* checking it directly OR do it faster than me

    下一篇: Flight request returning 406 error code on PUT / DELETE