Создать временный файл и автоматически удалить

Я пишу сценарий загрузки для защиты от личинга, и мой план состоит в том, чтобы создать временный файл, который будет назван по идентификатору сеанса, а затем, после истечения срока действия сеанса, файл будет автоматически удален. Является ли это возможным ? И можете ли вы дать мне несколько советов, как это сделать в PHP?

Большое спасибо за любой ответ


person mrblue    schedule 22.11.2009    source источник
comment
Как долго файл должен храниться?   -  person Ikke    schedule 22.11.2009
comment
Не могли бы вы уточнить, чего вы пытаетесь достичь? Скрипт Anti-Leeching DL немного расплывчатый. Что такое UseCase или проблема, которую пытается решить сценарий?   -  person Gordon    schedule 22.11.2009
comment
Привет, lkke, я просто хочу, чтобы пользователь загружал файлы только в своем сеансе, как будто он не может просто скопировать и вставить ссылку кому-то еще. Привет, Гордон, я хочу заставить пользователей загружать файлы с моего сайта, контролировать скорость. Итак, я думаю создать временный файл во временном каталоге в документах HTTP, чтобы пользователь мог их загрузить, а затем удалить (автоматически) после истечения сеанса.   -  person mrblue    schedule 22.11.2009
comment
может быть, вы могли бы как-то использовать IP-адрес пользователя?   -  person Philippe Gerber    schedule 22.11.2009
comment
Извините, я думаю, вы правы. Проверьте обновленный ответ   -  person Fluffy    schedule 23.11.2009


Ответы (7)


Итак, у нас есть один или несколько файлов, доступных для скачивания. Создание временного файла для каждого запроса на загрузку не является хорошей идеей. Вместо этого лучше создать symlink() для каждого файла. Это сэкономит много места на диске и снизит нагрузку на сервер.

Именование символической ссылки после сеанса пользователя — достойная идея. Лучшей идеей будет сгенерировать случайное имя символической ссылки и связать его с сеансом, чтобы скрипт мог обрабатывать несколько загрузок за сеанс. Вы можете использовать session_set_save_handler() (ссылка) и зарегистрировать пользовательскую функцию read, которая проверяет сеансы с истекшим сроком действия и удаляет символические ссылки, когда сеанс истек.

person leepowers    schedule 23.11.2009
comment
Привет pygorex1, это именно то, что я ищу. Большое спасибо. - person mrblue; 25.11.2009
comment
Ссылка теперь 404, просто пропинговал вас, чтобы вы могли это исправить. - person Mr. Alien; 20.02.2014

В PHP есть функция с таким именем tmpfile. Он создает временный файл и возвращает ресурс. Ресурс можно использовать как любой другой ресурс.

Например. пример из мануала:

<?php
$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
echo fread($temp, 1024);
fclose($temp); // this removes the file
?>

Файл автоматически удаляется при закрытии (используя fclose()) или при завершении скрипта. Вы можете использовать любые файловые функции на ресурсе. Вы можете найти их здесь. Надеюсь, что это поможет вам?

Другим решением было бы создать файл обычным способом и использовать cronjob для регулярной проверки, не истек ли срок действия сеанса. Дата истечения срока действия и другие данные сеанса могут храниться в базе данных. Используйте сценарий, чтобы запросить эти данные и определить, истек ли срок действия сеанса. Если это так, удалите его физически с диска. Обязательно запускайте скрипт раз в час или около того (в зависимости от вашего тайм-аута).

person TheGrandWazoo    schedule 22.11.2009
comment
Я не думаю, что это решение вопроса mrblue, потому что файл удаляется в конце скрипта/fclose(), а не по истечении срока действия сеанса. - person Philippe Gerber; 22.11.2009
comment
Ты прав, я думаю. Должно быть, читал эту часть. Добавил дополнительную информацию в свой пост. Теперь дело за ним ;) - person TheGrandWazoo; 22.11.2009
comment
Привет TheGrandWazoo, спасибо за ваш ответ. Я думал об этом решении, но это невозможно из-за проблемы с производительностью, если сайт масштабируется, и Филипп прав, меня беспокоит то, что PHP поддерживает функцию ловушки, например, автоматически вызывается после истечения срока действия или запуска сеанса. - person mrblue; 22.11.2009
comment
Нет необходимости задействовать базу данных при использовании cronjob. Когда файлы dl используют имя файла сеанса для этого пользователя, сценарий, вызываемый cron, просто должен удалить все файлы dl, для которых в настоящее время не существует файла сеанса. - person Gordon; 23.11.2009

Не могли бы вы объяснить свою проблему немного глубже? Потому что я не вижу причин, почему бы не использовать $_SESSION. Данные в $_SESSION хранятся на стороне сервера в файле (см. http://php.net/session.save-path) Кстати. По крайней мере, по умолчанию. ;-)

person Philippe Gerber    schedule 22.11.2009
comment
Привет, Филипп, Да, я действительно хочу использовать $_SESSION (на самом деле я это сделал), но я не могу найти ни одного документа или темы, в которых можно было бы упомянуть о чем-то, например, о действии ловушки: мы можем сделать функцию, которую система автоматически вызывает после окончания или начала сеанса. Это моя идея и забота. Спасибо за ваше время - person mrblue; 22.11.2009
comment
пойти другим путем. реагировать, когда создается новый сеанс (например, $_SESSION пуст, и вы заполнили его ранее), а не когда сеанс истекает. проблема в том, что сеанс может истечь без каких-либо действий со стороны пользователя (сеанс устарел и удален сборщиком мусора). что именно вы пытаетесь сделать? - person Philippe Gerber; 22.11.2009

Итак, у нас есть следующие требования на данный момент

  1. Разрешить пользователю скачивать только в его/ее сеансе
  2. не копировать и не вставлять ссылку кому-то другому
  3. Пользователи должны загрузить с сайта, например. нет хотлинкинга
  4. Контроль скорости

Посмотрим. Это не рабочий код, но он должен работать следующим образом:

<?php // download.php

session_start(); // start or resume a session

// always sanitize user input
$fileId  = filter_input(INPUT_GET, 'fileId', FILTER_SANITIZE_NUMBER_INT);
$token   = filter_input(INPUT_GET, 'token', FILTER_UNSAFE_RAW);
$referer = filter_input(INPUT_SERVER, 'HTTP_REFERER', FILTER_SANITIZE_URL);
$script  = filter_input(INPUT_SERVER, 'SCRIPT_NAME', FILTER_SANITIZE_URL);

// mush session_id and fileId into an access token
$secret        = 'i can haz salt?';
$expectedToken = md5($secret . session_id() . $fileId);

// check if request came from download.php and has the valid access token
if(($expectedToken === $token) && ($referer === $script)) {
   $file = realpath('path/to/files/' . $fileId . '.zip');
   if(is_readable($file)) {
        session_destroy(); // optional
        header(/* stuff */);
        fpassthru($file);
        exit;
    }
}
// if no file was sent, send the page with the download link.
?>
<html ...

<?php printf('a href="/download.php?fileId=%s&amp;token=%s', 
              $fileId, $expectedToken); ?>

...
</html>

И это все. База данных не требуется. Это должно охватывать требования 1-3. Вы не можете контролировать скорость с помощью PHP, но если вы не уничтожите сеанс после отправки файла, вы можете написать счетчик сеанса и ограничить количество файлов, которые пользователь будет отправлять во время сеанса.

Я полностью согласен с тем, что это можно было бы решить гораздо более элегантно, чем с помощью этого хака в форме обезьяны, но в качестве доказательства концепции этого должно быть достаточно.

person Gordon    schedule 22.11.2009
comment
Привет, Гордон, это почти 90% того, что я писал в своем коде, но у вас есть лучшая проверка безопасности с токеном. Большое спасибо за это. - person mrblue; 25.11.2009
comment
Токен повышает безопасность, но также избавляет вас от необходимости создавать символические ссылки или копировать файлы, поскольку токен уникален для сеанса и файла. Токен — это то, что pygorex1 создаст для имени символической ссылки. Просто вместо того, чтобы создавать из него симлинк, который потом нужно было бы как-то удалить, вы просто отправляете имя/токен с обычным fileId. Меньше обслуживания. - person Gordon; 25.11.2009

Я бы посоветовал вам не копировать файл в первую очередь. Я бы сделал следующее: когда пользователь запрашивает файл, вы генерируете случайную уникальную строку, чтобы дать ему ссылку следующим образом: dl.php?k=hd8DcjCjdCkk123 затем помещаете эту строку в базу данных, сохраняя его IP-адрес, возможно, сеанс и время, которое вы сгенерировали связь. Затем другой пользователь запрашивает этот файл, убеждается, что все вещи (хэш, ip и т. д.) совпадают, а срок действия ссылки не истек (например, с момента генерации прошло не более N часов), и если все в порядке, используйте PHP для передачи файл. Установите задание cron для просмотра БД и удаления просроченных записей. Что вы думаете?

tmpfile

Создает временный файл с уникальным именем в режиме чтения-записи (w+) и возвращает дескриптор файла. Файл автоматически удаляется при закрытии (используя fclose()) или при завершении скрипта.

person Fluffy    schedule 22.11.2009
comment
Я не думаю, что это решение вопроса mrblue, потому что файл удаляется в конце скрипта/fclose(), а не по истечении срока действия сеанса. - person Philippe Gerber; 22.11.2009
comment
Привет, роддик, Филипп был прав, я думал об этом решении, но оно неприменимо в моих обстоятельствах, особенно в отношении производительности. - person mrblue; 22.11.2009

Может быть, уже поздно отвечать, но я пытаюсь поделиться с вами в Google!

если вы используете CPanel, есть короткий и быстрый способ заблокировать внешний запрос к вашим размещенным файлам, имя которого: HotLink.

вы можете включить HotLinks на своей Cpanel и быть уверенным, что никто не сможет запросить ваш файл с другого хостинга или использовать ваши файлы в качестве ссылки для загрузки.

person Saeid A.K    schedule 20.06.2013

Чтобы добиться этого, я бы сделал один файл и защитил его с помощью chmod, сделав его недоступным для публики. Или, в качестве альтернативы, сохраните содержимое в строке таблицы базы данных и извлекайте его при необходимости.

Сделать его доступным для скачивания в виде файла. Для этого я бы получил содержимое из защищенного файла или, если он хранится в таблице базы данных, извлек его и просто вывел. Используя заголовки php, я бы дал ему желаемое имя, расширение, указал его тип и, наконец, заставил браузер загрузить вывод в виде сплошного файла.

Таким образом, вам нужно сохранить данные только в одном месте, либо в защищенном файле, либо в базе данных. Заставить клиентский браузер загружать его столько раз, сколько выполняются условия, например, пока пользователь вошел в систему и так далее. Не беспокоясь о дисковом пространстве, создавая временные файлы, cronJobs и / или автоматическое удаление файла.

person izzat ali Nazari    schedule 04.07.2015