Защита изображений на сайте с помощью ImageKit
В этом руководстве мы рассмотрим, как Instagram ограничивает доступ к URL-адресам изображений. Мы применим этот способ, чтобы защитить свой сайт от копирования графического контента.
Как Instagram защищает изображения?
Попробуем скопировать URL-адрес изображения, опубликованного в Instagram, а затем изменить его.

Что мы видим:
- Размер изображения, указанный в URL, не может быть изменен.
- Любая другая часть URL не может быть изменена или удалена.
Instagram также устанавливают срок жизни URL-адресов. В этом руководстве мы повторим это поведение.
Что создаем?
- Создадим небольшую галерею изображений.
- Реализуем некоторые методы защиты изображений, которые мы видели в предыдущем примере.
- Добавим на изображение водяной знак.
- Ограничим доступ к оригинальному изображению в высоком разрешении.
Ресурсы
- Знание HTML.
- Базовые навыки работы с NodeJS.
- Бесплатная учетная запись ImageKit.io. ImageKit.io - это комплексное решение для оптимизации и управления изображениями. Оно позволяет изменять размер изображения, обрезать наносить водяные знаки и т.д.
Базовая настройка
Для демонстрации создадим фотогалерею на тему еды:
1. Получаем URL-адреса для изображений
Загрузим изображения в медиа библиотеку, которая поставляется вместе с ImageKit.io. Здесь мы получим URL-адрес для каждого изображения.

Ниже приведен URL-адрес изображения, которое мы загрузили в медиа библиотеку ImageKit.io.
https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg
2. Создание HTML-разметки
Создадим HTML-код для размещения трех изображений.

Затем установим для изображений размер 300 на 300 пикселей. ImageKit.io поможет в этом. Можно использовать основанные на URL-адресах параметры преобразования в реальном времени, чтобы изменить размер изображения.
<img src="https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300" />
Также предоставим варианты изображения для экранов с высоким разрешением с помощью атрибута srcset в img и преобразования dpr.
<html>
<head>
<title>My Food Gallery Page</title>
</head>
<body>
<h1>My Food Gallery</h1>
<img
src="https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300"
srcset="https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300,
https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300,dpr-2 2x"
/>
<img
src="https://ik.imagekit.io/demo/img/scotch_security/2_fGwKLAgUUd.jpeg?tr=w-300,h-300"
srcset="https://ik.imagekit.io/demo/img/scotch_security/2_fGwKLAgUUd.jpeg?tr=w-300,h-300,
https://ik.imagekit.io/demo/img/scotch_security/2_fGwKLAgUUd.jpeg?tr=w-300,h-300,dpr-2 2x"
/>
<img
src="https://ik.imagekit.io/demo/img/scotch_security/3_xqMQs0ib3.jpeg?tr=w-300,h-300"
srcset="https://ik.imagekit.io/demo/img/scotch_security/3_xqMQs0ib3.jpeg?tr=w-300,h-300,
https://ik.imagekit.io/demo/img/scotch_security/3_xqMQs0ib3.jpeg?tr=w-300,h-300,dpr-2 2x"
/>
</body>
</html>
Защита изображений
Приступаем к реализации защиты изображений.
1. Водяной знак для изображения
Одним из способов защиты изображений является нанесение на них водяных знаков. Логотип водяного знака мы загрузили в библиотеку ImageKit.

Этот логотип доступен по следующему адресу:
https://ik.imagekit.io/demo/img/scotch_security/secure_cr21l_7GU.png
Для нанесения водяных знаков на изображения используем инструмент ImageKit. Теперь URL-адрес нашего изображения выглядит следующим образом:
<img src="https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg
?tr=w-300,h-300
,oi-@@scotch_security@@secure_cr21l_7GU.png
,ofo-bottom_right
,ow-150" />
Само изображение теперь выглядит так.

Добавление водяного знака гарантирует, что никто не сможет использовать ваше изображение на своем сайте.
2. Предотвращение изменения URL-адреса или удаления водяного знака
Но ведь можно посмотреть URL-адрес, удалить параметры наложения водяного знака и получить изображение. То же самое относится и к любому другому параметру в URL-адресе.

Исправим это.
Часть а. Генерация «подписанного» URL-адреса
Подпишем URL-адрес изображения с помощью хеш-кода, созданного с помощью алгоритма SHA1и секретного ключа, который известен только клиенту и серверу (клиент – это мы, а сервер изображений – ImageKit).
Сгенерируем хеш и передадим его вместе с остальной частью URL-адреса на сервер изображений. Затем сервер создаст подпись для всего URL-адреса с использованием того же закрытого ключа и сравнит ее с подписью, полученной от клиента.
Если подписи совпадают, запрос обрабатывается. Если нет, то URL-адрес или подпись были подделаны и выполнение запроса блокируется.
В ImageKit создать подписанный URL-адрес довольно просто. Для этого применяется один из предоставляемых SDK. В примере ниже мы используем SDK NodeJS.
/__
Будет выполнено на сервере NodeJS
__/
var imagekit = new ImageKit({
privateKey : "our_private_key", // это основной параметр, необходимый для генерации подписи ...
});
var signedURL = imagekit.url({
src : "https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150",
signed : true // этот параметр помогает в создании подписанного URL
});
Подписанный URL-адрес, созданный с помощью SDK, выглядит следующим образом:
https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=b19a8d348746e1e7f89a8c0262507ce36ad41a3d
В конце URL-адреса есть дополнительный параметр ik-s.
Для простоты мы генерируем подпись и заменяем существующий URL-адрес в HTML новым подписанным URL-адресом. В реальных условиях сервер использует шаблон для генерации HTML. Таким образом, именно сервер генерирует подписанные URL-адреса и использует их в тегах img.
Часть б. Ограничение доступа к неподписанному URL-адресу изображения
Также необходимо, чтобы сервер изображений, не отвечал запросы изображений, к которым не будет прикреплена действительная подпись. Для этого ImageKit использует параметр, который блокирует любые неподписанные запросы.

Результат после генерации подписи
Вот так выглядит HTML с новыми подписанными URL-адресами изображений.
<html>
<head>
<title>My Food Gallery Page</title>
</head>
<body>
<h1>My Food Gallery</h1>
<img
src="https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=7cf746087e01ed1d3ad58ca64156745070e69e3e"
srcset="https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=7cf746087e01ed1d3ad58ca64156745070e69e3e,
https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300,dpr-2,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=02bd8e66a0000dbdb73619211743c8f6fa5addf0 2x"
/>
<img
src="https://ik.imagekit.io/demo/img/scotch_security/2_fGwKLAgUUd.jpeg?tr=w-300,h-300,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=1bbab2b2fc63abdaf585197b1d9707220cc07b6c"
srcset="https://ik.imagekit.io/demo/img/scotch_security/2_fGwKLAgUUd.jpeg?tr=w-300,h-300,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=1bbab2b2fc63abdaf585197b1d9707220cc07b6c,
https://ik.imagekit.io/demo/img/scotch_security/2_fGwKLAgUUd.jpeg?tr=w-300,h-300,dpr-2,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=9030030923deada4531f619e033660ba510499d6 2x"
/>
<img
src="https://ik.imagekit.io/demo/img/scotch_security/3_xqMQs0ib3.jpeg?tr=w-300,h-300,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=ec65c1f6354de6bb4e16d2ae3bb13b3828f9816e"
srcset="https://ik.imagekit.io/demo/img/scotch_security/3_xqMQs0ib3.jpeg?tr=w-300,h-300,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=ec65c1f6354de6bb4e16d2ae3bb13b3828f9816e,
https://ik.imagekit.io/demo/img/scotch_security/3_xqMQs0ib3.jpeg?tr=w-300,h-300,dpr-2,oi-@@scotch_security@@secure_cr21l_7GU.png,ofo-bottom_right,ow-150&ik-s=b71bc7d5e9d0e11b8af5c1250ec50ae546e165ad 2x"
/>
</body>
</html>
Использование не подписанного URL-адреса теперь приведет к ошибке. Подобное мы видели в Instagram.
Теперь никто не может удалить водяной знак с изображения или скачать его в другой размерности.

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

Также нужно убедиться, что срок действия URL-адреса истекает через один час. Для этого мы передаем в исходном коде другой параметр, указывающий количество секунд до истечения срока действия URL-адреса.
var signedURL = imagekit.url({
src : "https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg?tr=w-300,h-300",
signed : true // этот параметр помогает в создании подписанного URL
expireSeconds : 3600 // количество секунд до окончания срока действия URL
});
Это дает нам следующий URL-адрес:
https://ik.imagekit.io/demo/img/scotch_security/1_GTMtFxEf5.jpeg
?tr=w-300,h-300
&ik-s=f65fd8e3136b557e61dc69c2ed19182f07a1ce5
&ik-t=1234567890
В приведенном выше URL используется дополнительный параметр запроса ik-t, который является временной меткой.
Настройка параметров подписи для конкретного изображения, а не для всей учетной записи
В ImageKit доступна функция, позволяющая наложить ограничение на неподписанные URL-адреса, относящиеся к конкретному изображению, а не ко всей учетной записи.
Она называется приватные изображения. Мы можем пометить изображение как «приватное», когда загружаем его в библиотеку ImageKit. Доступ к такому изображению возможен только через подписанные URL-адреса, даже если настройка использования подписанных URL отключена.
Заключение
ImageKit упрощает реализацию защиты изображений. Такие сервисы, как Instagram, уже используют подобные инструменты для URL-адресов изображений. Реализуйте это для своих изображений с помощью ImageKit.