19

我在“即使清除浏览器 cookie 后网站如何跟踪用户”的答案中读到,可以通过网站图标跟踪用户:

Favicons 是第三种可能性——大多数浏览器在页面加载之前请求它,所以如果该请求得到满足,那么客户端显然是重复访问者。

如果这实际上是可能的,它可能是检查用户之前是否访问过该网站的好方法,不需要为该海豚使用 cookie。

我不确定这是否可以用 PHP 或 Javascript (jQuery) 完成。如何做到这一点?

编辑

我对此的解释是用户在需要 Favicon 时会拨打电话。如果他不打那个电话,这意味着他已经有了这个网站图标,所以他访问了。因此无需在用户计算机中存储任何文件(例如 cookie)或将其 IP 保存在服务器中。这个对吗?

4

7 回答 7

15

您需要做两件事。首先,您需要将网站图标请求重定向到脚本。您可以通过两种方式做到这一点。第一个是在您的.htaccess文件中添加类似以下内容

RewriteEngine on
RewriteRule ^/favicon.ico   /favicon.php  [L]

或者您可以在 html 代码中发送另一个网站图标位置。但是,我不会使用它直接重定向到 php 脚本,因为某些浏览器在正确使用 favicon 时会出现问题,如果它不是真正的 a.ico.png文件。也许您可以使用它来重定向到另一个favicon.ico位置并将其与.htaccess. 我为所有设置使用了一个图标位置,这并不是真正需要的。但是这样你就知道如何改变它了。

<link rel="icon" href="/favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<link rel="icon" href="/favicon.ico" type="image/x-icon" sizes="32x32">
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" sizes="32x32">

由于您正在重定向到 PHP 脚本,因此您可以使用下面的代码来处理实际请求。

<?php
//the location of the actual favicon
$favicon = '/favicon.ico';
$protocol = (isset($_SERVER['SERVER_PROTOCOL'])) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0';

//try to get the file info, to be able to get the correct content type
//if it doesnt work, return 404 error
$size = @getimagesize($favicon);
if (!$size) {
  header($protocol . ' 404 Not Found');
  exit();
}

// Content type
header('Content-type: ' . $size[2]);

//when is the icon last modified
//Keep in mind that if you modify the icon, all returning visitors will be handled as new visitors
$last_modified_time = @filemtime($favicon);

header("Accept-Ranges:  bytes");
//set a long max-age with a recheck marker, so people check if the icon is still the same and thus access this script.
header("Cache-Control: max-age=15724800, public, must-revalidate");
header("Vary: Accept-Encoding");
//some say the Etag is bad, some say it isnt. You can remove this part if you dont want to use it.
header("Etag: " . md5($favicon . $last_modified_time));


// exit if not modified
if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) {
  if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time) { 
      header($protocol .' 304 Not Modified'); 

      /*
      At this point you have a returning visitor.           
      */
      DoSomethingWithReturningVisitor();

      exit();
  }
}

// exit if not modified using Etag, remove it if you dont want to use it.
if (array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER)) {
  if ($_SERVER['HTTP_IF_NONE_MATCH'] == md5($favicon . $last_modified_time)) { 
      header($protocol.' 304 Not Modified'); 


      /*
      At this point you have a returning visitor.           
      */
      DoSomethingWithReturningVisitor();


      exit();
  }
}

//you are sending a new image to the user. Add the last modified time.
header("Last-Modified: ".gmdate("D, d M Y H:i:s", $last_modified_time)." GMT");


//log that he is a new visitor
//If you dont to this, the user will be marked as returning visitor when he visits the 2nd page of your website
$_SESSION['newVisitor'] = true;

//return the content of the actual image
echo file_get_contents($favicon);


//A single point to handle returning visitors
//make sure you dont have any output in this function, because you are still returning a valid favicon. If you have any output the returned icon will be corrupted.

function DoSomethingWithReturningVisitor() {
  if (!empty($_SESSION['newVisitor']) && $_SESSION['newVisitor'] === true) {
    //already marked as new visitor, so skip for this session
    return;
  }

  //do something to give this user special treatment
  $_SESSION['returningVisitor'] = true;
}
?>

现在,在对您的网页的第一次请求中,这将很难跟踪。因为首先会向您的主页发出请求,然后它会尝试加载favicon.ico. 因此,新/回访者的信息不能直接在 php 中获得。检查主页顶部是否是回访者的最佳方法是

<?php
if (empty($_SESSION['returningVisitor']) && empty($_SESSION['newVisitor'])) {
   //unknown if user is new or not
} else if (!empty($_SESSION['returningVisitor']) && $_SESSION['returningVisitor']===true) {
   //returning visitor
} else {
   //new visitor
}
?>

如果您真的需要在主页(或用户请求作为此会话的第一页的任何其他页面)上知道它,您最好的选择是在加载文档时进行 ajax 调用,即使超时时间很短,因为favicon.ico 请求并不总是正文的一部分。

于 2013-06-05T07:08:30.373 回答
6

要在 Apache 中获取有关网站图标请求的信息,请编辑您的 .htaccess 文件以将网站图标请求重新路由到您选择的脚本。然后,您需要记录请求 IP 地址或使用 cookie 来确定站点访问者是否刚刚请求了网站图标。

编辑
请记住在处理请求后返回网站图标。

于 2013-05-30T05:59:00.537 回答
2

我不确定这是否可以用 PHP 或 Javascript (jQuery) 完成。如何做到这一点?

您可能想了解客户端和服务器端编程的区别。

在您的情况下,您是从服务器的角度来看的,因此您希望利用服务器端功能(可能还有编程)。因此,这种非 cookie favicon HTTP 请求跟踪可以通过您的服务器在服务器端实现。您的服务器知道何时请求了网站图标,只需记录请求并解释数据即可。

我对此的解释是用户在需要 Favicon 时会拨打电话。如果他不打那个电话,这意味着他已经有了这个网站图标,所以他访问了。

没错,但是您还应该在某些情况下对此进行测试。例如,浏览器可能会也可能不会考虑HTTP 缓存。因此,了解规范,了解它的用途,根据这些规范实施您对数据的解释,并使用不同的浏览器和计算机对其进行现场测试。

因此无需在用户计算机中存储任何文件(例如 cookie)或将其 IP 保存在服务器中。这个对吗?

好吧,如果你想解释它,你至少需要存储一些东西。从技术上讲,它不能是一个文件(例如,您也可以存储到共享内存中),但是,您需要有一些数据可以使用,这通常需要将其存储(某处)。

于 2013-06-10T08:43:07.450 回答
1

当浏览器向您的服务器请求任何内容时,它会发送所有 cookie 等。对于 favicon 也是如此。

要让 PHP “拦截”这些请求,您需要强制 Apache(或您使用的任何 HTTP 服务器)将 favicon 视为 php 文件。

在您的 .htaccess 类型中(再次假设 apache)

<FilesMatch "^favicon.ico$"> 
ForceType application/x-httpd-php
SetHandler application/x-httpd-php
</FilesMatch>

现在,对于 favicon,服务器现在需要一个 php 文件,而客户端需要一个图标。所以在 php 之外根本不能有空白,否则图标将不起作用。首先将您的真实 favicon 移动到 real-favicon.ico,然后使用以下内容创建一个新的 favicon.ico

<?php
//do any processing you wish here, all cookies etc are available if needed 

header('Content-type: image/x-icon');
echo file_get_contents ("real-favicon.ico");

您不需要最后一个?> 所以将其关闭可能更安全,因为一些编辑器在底部放置了空白区域,这会破坏图像。

如果没有这种方法,您将不得不解析 apache 日志以查找这些和匹配的 IP。

您仍然需要 cookie 信息,没有它就无法传递/跟踪信息。

于 2013-06-05T00:15:34.957 回答
0

您提到的答案没有解释该技术。

使用网站图标识别用户的技巧是通过为每个用户提供唯一的网站图标 URL 来实现的。

此外,favicon 带有需要浏览器重新验证的标头。

当用户浏览器重新验证favicon时,它的唯一名称将被传递,IP地址可以被禁止。

于 2013-06-08T16:20:46.843 回答
0

您可以使用基于网络服务器的重定向/重写将 favicon 请求传递给您选择的服务器端语言。实施取决于您的网络服务器和语言的风格。但是,如果您要让脚本直接处理此问题,则不妨从页面进行跟踪。

或者,如果您不需要实时信息,您可以尝试阅读日志文件。如果这是他们的方式,那么您可能会获得更可靠的结果来跟踪 robots.txt。此外,根据您的网络服务器,日志可能不包含您需要的所有信息(时间戳、IP 等)。

但是,我强烈建议不要为此使用网站图标。对于何时请求网站图标并且浏览器以不同方式处理它,没有明确的规则集。他们可能会在不访问网站的情况下请求网站图标(只是为了更新书签),或者他们可能会定期请求。请求网站图标也不仅限于浏览器;许多网络应用程序使用网站图标显示在链接旁边。所有这些意外命中都可能使统计数据变得非常不可靠。

于 2013-06-05T16:21:53.233 回答
-3

要么使用对不同浏览器跟踪不太好的“cookie”,要么使用 PHP 来跟踪 IP 地址。

于 2013-05-30T05:54:45.877 回答