Мониторинг доступа к изображению И/ИЛИ предотвращение прямого доступа

Я хочу, чтобы пользователи видели изображение как часть веб-страницы, но я хочу, чтобы они не обращались к изображению напрямую. Это может, скажем, дать подсказки в URL-адресе о том, с каким пользователем они связаны (недостаток, который я видел в одном приложении facebook).

Как я могу отслеживать доступ к изображениям и/или предотвращать прямой доступ к изображениям (например, путем перезаписи URL-адресов...)?

Решения, предложенные до сих пор:

  • Использование заголовков (надежно?)
  • Затруднить доступ к изображениям (например, установить изображение в качестве фона div).
  • ...

person James P.    schedule 30.07.2011    source источник
comment
Вы можете проверить заголовок реферера; если изображение загружается с вашего веб-сайта, реферер должен быть URL-адресом на вашем домене. Однако это не является надежным, некоторые программы и прокси-серверы для блокировки рекламы / обеспечения конфиденциальности удаляют заголовок реферера, делая его похожим на прямой доступ, когда это не так.   -  person Dan Grossman    schedule 30.07.2011
comment
сделать изображение фоном div - пользователю будет сложнее получить прямую ссылку (но возможно).   -  person OZ_    schedule 30.07.2011
comment
Метод с проверкой реферера неправильный. Рефереры могут быть пустыми, могут быть даже неправильными (с адресом предыдущей страницы, а не текущей).   -  person OZ_    schedule 30.07.2011


Ответы (4)


Пуленепробиваемого способа нет. Однако вы можете использовать эвристику. Проверьте следующие заголовки:

  1. Referer -- этот заголовок будет присутствовать, если изображение было запрошено браузер в результате тега <img> или CSS. Этот заголовок будет пустым, если изображение было запрошено напрямую (путем ввода URL-адреса в адресной строке). Если этот заголовок содержит другой домен, значит, этот другой веб-сайт сделал ссылку на ваше изображение. Обратите внимание, что это ожидаемое поведение, но не гарантируется, что каждый браузер будет вести себя таким образом.

  2. Accept -- этот заголовок будет содержать строку, например image/*, когда изображение было запрошен, так как браузер обнаружил, что он встроен в теги HTML или CSS. Когда кто-то запрашивает изображение напрямую, набрав в браузере, вы найдете такие значения, как text/html,application/xhtml+xml и т. д. Это связано с тем, что браузер не знает, чего ожидать, когда он запрашивает http://website.com/someimage.jpg< /эм>; следовательно, он предпочтительно будет запрашивать text/html контент.

В Apache вы можете проверять (и сопоставлять) заголовки HTTP, чтобы определить, доступен контент или нет. Я не уверен насчет других платформ, но вы можете написать общий прокси-скрипт для обслуживания изображений.

Редактировать

Если URL-адрес изображения раскрывает информацию, которую вы не хотите раскрывать, вы можете запутать ее, используя хэши или шифрование. Поэтому вместо того, чтобы обслуживать такой контент, как:

<img src="/images/users/12345.jpg">

Вы будете писать:

<img src="/images/users/image.php?hash=<?php echo md5('secret' . '12345'); ?>">

Вам нужно написать скрипт, который отправляет соответствующее изображение в браузер.

person Salman A    schedule 30.07.2011
comment
because browser does not know what to expect when it requests http://website.com/someimage.jpg - лол, какой браузер настолько глуп, что не читает .jpg в URL? И ваши первые «правила» о реферере совершенно неверны. Referrer может быть пустым или может содержать другой домен... просто так (вы можете это проверить). Поведение этого заголовка очень непредсказуемо. - person OZ_; 30.07.2011
comment
@SalmanA: также, когда вы щелкаете правой кнопкой мыши и щелкаете, чтобы показать изображение, он также отправит реферер - person genesis; 30.07.2011
comment
@OZ_... глупый браузер - FF4. попробуйте вставить этот URL в адресную строку и скажите, какие заголовки Вы получаете. Что касается реферера, я отредактирую свой ответ и подчеркну, что это не пуленепробиваемый; но поведение, которое я упомянул, является ожидаемым поведением в большинстве случаев. Почему бы вам не проверить себя, прежде чем голосовать? - person Salman A; 30.07.2011
comment
@Генезис: правда. Я никогда не говорил о пуленепробиваемости. - person Salman A; 30.07.2011
comment
@Salman А это не expected behavior is most cases, это просто твои предположения. У меня нет FF4, я протестировал заголовок «Accept» в Opera, и в обоих случаях этот заголовок содержит: Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/webp, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1. В Chrome: встроенный: */*, прямой: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8. - person OZ_; 30.07.2011

Если позволите, кое-что, что снова не является пуленепробиваемым, но обманывает многих, — это использование изображения в качестве фона. В своем HTML-коде поместите тег изображения, заполненный специальным прозрачным GIF-файлом размером 1 на 1 пиксель (blank.gif примерно в формате html-таблицы) и измените его размер до размеров вашего фактического изображения. Затем установите его фоновое изображение как фактическое изображение. Это обманет многих пользователей, которые знают только, как щелкнуть правой кнопкой мыши, чтобы загрузить/получить URL-адрес изображения.

<html>
<head>
    <style>
        #logo { background: url(my-logo.png); width: 100px; height: 50px; } /* Change this to match your image name and dimensions */
    </style>
</head>
<body>
    <img src="blank.gif" id="logo">
</body>
</html>

Я знаю, что это не поможет, если пользователь печатает экраны (но не поможет ни один метод), но это решение для менее осведомленных пользователей. Кроме того, такие сайты, как Youtube, уже используют этот метод, поэтому, если он достаточно хорош для Google, я бы сказал, что он достаточно хорош для вас или для меня!

РЕДАКТИРОВАТЬ: Пожалуйста, извините мое полное отсутствие сознания, поскольку это уже опубликовано в качестве комментария. Я начал писать до того, как это было опубликовано.

person Bailey Parker    schedule 30.07.2011

Как уже говорилось, для этого нет серебряной пули (например, вы не можете запретить пользователю делать снимок экрана)

Но если вы хотите защитить свои изображения от анонимного доступа, вы можете использовать «прокси-сервер» php, который проверит, разрешено ли пользователю видеть это изображение, а затем загрузит его.

Вот очень простой пример кода для такого прокси. Если вы действительно хотите защитить свои изображения, храните их вне корня документа.

<?php

//Sample image protection proxy. Do not use as is.

//Let's monitor the authorized accesses
session_start();
$mon = isset($_SESSION['mon']) ? $_SESSION['mon'] : 0;


//Let's simulate an auth mecanism
$allowed = isset($_GET['allowed']) ? (int)$_GET['allowed'] : 0;

if ($allowed === 1) {
    // DO NOT USE AS IS ! add security checks to prevent XSS, especially if images are uploaded by untrusted users
    $img = file_get_contents('img.png');
    $mon++;
    $_SESSION['mon'] = $mon;
    header('content-type:image/png');
    echo $img;
} else {
        //handle unauthorized access here.
    //For this example, I send some plain text
    header('content-type:text/plain');
    echo 'You are not allowed to see that picture.'.PHP_EOL;
    echo 'This picture has been opened : '.$mon. ' times.'; 
}
?>

Если вы хотите протестировать этот скрипт:

Надеюсь, это поможет !

person Benjamin Dubois    schedule 30.07.2011

Вот идея, которая может сработать, хотя я не слишком много обдумывал ее и не пробовал:

  1. Сервер получает запрос на страницу.
  2. Создайте содержимое страницы в PHP, используя одноразовый ключ (OTK), который ссылается на изображение. OTK может храниться в переменной сеанса или в базе данных.
  3. Когда клиент отображает страницу, сервер получает запрос через параметр запроса для изображения, используя OTK. Поставьте образ и удалите ОТК.

Например, вместо:

<img src="www.mysite.com/mypage/myimage.jpg">

... создайте одноразовый ключ и сохраните его в таблице поиска, чтобы он ссылался на ваше изображение:

4e33fd162fe95 => image.jpg

... затем создайте свою страницу, используя вместо этого OTK:

<img src="www.mysite.com/mypage?image=4e33fd162fe95">

Когда сервер получит запрос на это изображение, отправьте изображение и удалите OTK. Это означает, что каждый запрос страницы генерирует новый OTK. Повторная попытка использовать этот URI для изображения не сработает.

Это имеет некоторые очевидные недостатки с точки зрения производительности, так как кэширование на стороне клиента больше не будет работать, а это создаст некоторые накладные расходы на сервер. Вероятно, есть и другие предостережения.

person Mike    schedule 30.07.2011