Создать временную ссылку для скачивания - PullRequest
3 голосов
/ 18 апреля 2011

Я использую ASP.NET
Мне нужно дать пользователю временную ссылку для скачивания файла с сервера.
Это должна быть временная ссылка (страница), которая доступна в течение короткого времени (например, 12 часов). Как я могу сгенерировать эту ссылку (или временную веб-страницу со ссылкой)?

Ответы [ 5 ]

8 голосов
/ 07 июня 2013

Вот достаточно полный пример.

Сначала функция для создания короткой шестнадцатеричной строки с использованием секретной соли плюс время истечения:

public static string MakeExpiryHash(DateTime expiry)
{
    const string salt = "some random bytes";
    byte[] bytes = Encoding.UTF8.GetBytes(salt + expiry.ToString("s"));
    using (var sha = System.Security.Cryptography.SHA1.Create())
        return string.Concat(sha.ComputeHash(bytes).Select(b => b.ToString("x2"))).Substring(8);
}

Затем фрагмент, который генерирует ссылку с истечением в одну неделю:

DateTime expires = DateTime.Now + TimeSpan.FromDays(7);
string hash = MakeExpiryHash(expires);
string link = string.Format("http://myhost/Download?exp={0}&k={1}", expires.ToString("s"), hash);

Наконец, страница загрузки для отправки файла, если была дана действительная ссылка:

DateTime expires = DateTime.Parse(Request.Params["exp"]);
string hash = MakeExpiryHash(expires);
if (Request.Params["k"] == hash)
{
    if (expires < DateTime.UtcNow)
    {
        // Link has expired
    }
    else
    {
        string filename = "<Path to file>";
        FileInfo fi = new FileInfo(Server.MapPath(filename));
        Response.ContentType = "application/octet-stream";
        Response.AddHeader("Content-Disposition", "attachment;filename=" + filename);
        Response.AddHeader("Content-Length", fi.Length.ToString());
        Response.WriteFile(fi.FullName);
        Response.Flush();
    }
}
else
{
    // Invalid link
}

Который вы, безусловно, должны обернуть при обработке исключений, чтобы перехватить искаженные запросы.

6 голосов
/ 18 апреля 2011
http://example.com/download/document.pdf?token=<token>

Часть <token> является ключевой здесь.Если вы не хотите использовать базу данных, зашифруйте время создания ссылки, преобразуйте ее в безопасное для URL представление Base64 и предоставьте пользователю этот URL.Когда это запрошено, расшифруйте token и сравните сохраненную там дату с текущей датой и временем.

В качестве альтернативы, вы можете иметь отдельную таблицу DownloadTokens, которая сопоставит указанные token s (которые могут быть GUID) до истечения срока годности.

3 голосов
/ 23 июня 2011

Добавьте метку времени к URL-адресу в строке запроса:

page.aspx?time=2011-06-22T22:12

Проверьте метку времени по отношению к текущему времени.

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

page.aspx?time=2011-06-22T22:12&timehash=4503285032

В качестве хеша вы можете сделать что-то вроде суммы всех полей в DateTime по модулю некоторого простого числа или суммы строки SHA1представление времени.Теперь пользователь не сможет изменить метку времени, не зная правильный хеш.В вашем page.aspx вы проверяете данный хеш по хешу временной метки.

1 голос
/ 18 апреля 2011

лля

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

Лично я бы создал HttpHandler, а затем создал бы уникальную строку, которую вы можете добавить к URL.

Затем в рамках vid ProcessRequest протестируйте закодированный параметр, чтобы увидеть, является ли он все еще жизнеспособным (с указанным вами периодом времени), если это так, используйте BinaryWrite для визуализации файла или, если нет, вы можете визуализировать некоторый HTML-код с помощью Response.Write ("Expired «)

Что-то вроде:

public class TimeHandler : IHttpHandler, IRequiresSessionState
{
    public void ProcessRequest ( HttpContext context )
    {

        if( this.my_check_has_expired( this.Context.Request.Params["my_token"] ) )
        {
            // Has Expired 

            context.Response.Write( "URL Has Expired" );
            return;
        }

        // Render the File
        Stream stream = new FileStream( File_Name , FileMode.Open );

        /* read the bytes from the file */
        byte[] aBytes = new byte[(int)oStream.Length];
        stream.Read( aBytes, 0, (int)oStream.Length );
        stream.Close( ); 

        // Set Headers
        context.Response.AddHeader( "Content-Length", aBytes.Length.ToString( ) );
        // ContentType needs to be set also you can force Save As if you require

        // Send the buffer
        context.Response.BinaryWrite( aBytes );                            

    }
}

Затем необходимо настроить обработчик в IIS, но он немного отличается в зависимости от используемой версии.

1 голос
/ 18 апреля 2011

Есть миллион способов сделать это.

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

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