Подписанные ссылки

Почти все REST сервисы имеют аутентификацию. Есть несколько способов её сделать:

  • basic. В каждый запрос добавляется заголовок “Authorization” с логином и паролем.
GET / HTTP/1.1
Host: example.org
Authorization: Basic Zm9vOmJhcg==
  • token. REST сервис обменивает логин и пароль на специальный токен аутентификации. Клиент должен все последующие запросы делать с этим токеном.
GET / HTTP/1.1
Host: example.org
Authorization: Bearer 9yro9yueihfw497y33497y3oeiruhfvskdgjhfaowidayuh

Аутентификация на основе токенов наиболее безопасная и гибкая. Токены можно отзывать и обновлять, в них можно класть дополнительную информацию. С ними очень удобно работать из SPA приложений. Например, доступ к защищённому ресурсу можно сделать следующим образом:

  • Установить единый токен для всех запросов
axios.defaults.headers.common['Authorization'] = 'Bearer ' + token
  • Делать вызывы к защищённым методам
$http.get('/admin/config/general').then(function (response) {
	console.log(response)
})

Но что делать, если необходимо защитить статические ресурсы? Например, в r2cloud статические ресурсы это снимки со спутников, телеметрия и метрики производительности. Есть несколько способов.

Data-src атрибут

Схема работы следующая:

  • Вместо обычного src атрибута, указывается data-src
<img data-src="/admin/observation/picture.png">
  • После загрузки страницы код на javascript должен проходить по всем элементам img, загружать через ajax картинки и проставлять их в тэг src
$("img").attr("src", "data:image/png;base64," + response);

У этого метода есть один большой недостаток: необходимо на каждой странице выполнять javascript код, который будет подгружать картинки. Но есть и другой способ.

Подписанные ссылки

Суть метода заключается в том, что к ссылке добавляется подпись. Эта подпись обладает следующими свойствами:

  • позволяет получить данные без использования заголовка Authorization.
  • короткоживущая. Подпись содержит в себе время создания ссылки. Это время проверяется на сервере, и если оно превышает время жизни ссылки, то её данные нельзя получить.
  • её нельзя подделать. Она сгенерирована с использованием секретного ключа, который известен только на сервере.

Вот как выглядит использование таких ссылок на странице:

<img src="/img/a.jpg?hash=3679d97d8b1d497743cd8da8ba0440f5&timestamp=1508716800000">

Где hash - это подпись, timestamp - время генерации ссылки. На сервере подпись можно генерировать следующим образом:

computeMD5(path + timestamp + password)

Здесь нужно обратить внимание на то, что время включено в алгоритм генерации подписи. Это позволит защититься от атак повторного воспроизведения.

Кэширование

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

Cache-Control: private, max-age=600
Last-Modified: Wed, 15 Nov 1995 04:58:08 GMT