使用mod_rewrite保存HTTP_REFERER?

时间:2010-08-27 06:51:54

标签: .htaccess rewrite mod-rewrite referrer http-referer

实际上我正试图在.htaccess中传递引用。我要做的是将referer值发送到PHP脚本,其中该值将保存到数据库。在某些情况下(取决于引用者)图像应被阻止(热链接),在某些情况下,图像应正常显示。但它不起作用:-(我目前的“尝试”看起来如下(它只是用于测试,因此目前每个图像都将被处理):

RewriteCond %{REQUEST_URI} (.*)jpg$
RewriteCond %{ENV:verified}  ^$  
RewriteRule (.*)jpg$   /include/referrer.php?ref=%{REQUEST_FILENAME}&uri=%{REQUEST_URI}&query=%{QUERY_STRING}&env=%{ENV:verified} [E=verified:yes]

RewriteCond %{REQUEST_URI} (.*)jpg$
RewriteCond %{ENV:verified} ^yes$
RewriteRule ^(.*)$    %{REQUEST_FILENAME} [E=verified:no]

referrer.php看起来像:

<?
 log_img($_REQUEST['uri'].' - "'.$_REQUEST['env'].'"');
?>

问题在于调用了referrer.php,但是不会显示图像,这很明显,因为未达到第二个规则。

我也尝试在referrer.php中显示图像,如:

<?
 log_img($_REQUEST['uri'].' - "'.$_REQUEST['env'].'"');
 $src = str_replace($_SERVER['DOCUMENT_ROOT'],'',$_REQUEST['ref']);
?>
<img src="<? echo $src ?>" />

然后再次调用.htaccess,我会遇到无休止的循环。

现在的问题是:如何访问第二条规则或如何实现我想要做的事情。有没有办法做到这一点?

感谢您的帮助, 拉斯

1 个答案:

答案 0 :(得分:0)

您当前的解决方案不起作用,因为mod_rewrite只能用于将请求重写到单个目标,但您似乎希望请求绕过您的PHP脚本,然后继续前进到图片。有可能导致子请求导致PHP脚本被触发,但我不认为可以控制原始请求是否继续在该场景中的图像。

这里最好的做法是让你的PHP文件在执行你打算做的任何检查/记录之后打印出实际的图像数据(不是引用图像的图像标记)。只要您发送了正确的标题,就可以使用readfile()执行此操作。确保文件是您要提供的图像之一(而不是系统中的任意文件...),您至少需要determine the appropriate content type,然后打印出数据。考虑缓存(参见this answer以及this one)也是一个好主意。

结合提到的一些技术,引用者脚本的简单伪示例如下。请注意,您应该研究实现所描述技术的最佳方法,并且您需要特别注意安全性,因为您打开文件并打印其内容。

$filename = /* sanitized file name */;

log_img(/* log some data about the request */);

if (file_exists($filename) && allowedToView($filename)) {
    // Assume we're not on PHP 5.3...
    $types = array(
        'gif' => 'image/gif',
        'png' => 'image/png',
        'jpg' => 'image/jpg',
    );
    $parts = pathinfo($filename);
    $ext   = strtolower($parts['extension']);

    if (array_key_exists($ext, $types)) {
        $mime = $types[$ext];
        $size = filesize($filename);
        $expires  = 60 * 60 * 24 * 30;

        if (!empty($_SERVER['IF-MODIFIED-SINCE'])) {
            $modified = filemtime($filename);
            $cached   = strtotime($_SERVER['IF-MODIFIED-SINCE']);

            if ($modified <= $cached) {
                header('HTTP/1.1 304 Not Modified');
                exit();
            }
        } 

        header("Content-Type: $mime");
        header("Content-Length: $size");
        header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $expires)
            . ' GMT');
        header('Cache-control: private, max-age=' . $expires);
        readfile($filename);
        exit();
    }
}

header("HTTP/1.0 404 Not Found");
exit();

就.htaccess文件而言,它就是这样的(你在查询字符串中添加的东西无论如何都在$_SERVER中可用,所以我认为没有必要手动将它传递给脚本):

RewriteEngine on

RewriteRule \.(jpg|png|gif)$ /include/referrer.php [NC]