У двох попередніх сценаріях я використовую короткоживучі підписані URL, але для різних операцій.
Перший сценарій - це тимчасове посилання для читання приватного файла. Другий - пряме завантаження файла у S3-сумісне сховище.
На рівні сховища обидва рішення можуть виглядати схоже: застосунок створює підписану адресу з моментом завершення дії.
Але з погляду безпеки це різні права. Одне дозволяє прочитати вже існуючі дані. Інше дозволяє записати нові.
Саме тому я не використовую для них один спільний строк дії лише заради зручності конфігурації.
Одна технологія не означає однаковий ризик
Read URL existing object | vtemporary permission | vGET object Upload URL future object path | vПідписаний URL не є просто "посиланням на файл".
У ньому закладено конкретну операцію, конкретний об’єкт або шлях, параметри запиту і строк дії.
Тому однаковий механізм підпису не робить читання і запис однаковими з точки зору ризику.
URL для завантаження дає право створити або записати об’єкт
Коли застосунок видає URL для прямого завантаження, він фактично дозволяє клієнту записати дані у визначений ключ сховища.
Навіть якщо ключ створив сервер і право дуже вузьке, це все одно операція запису.
Чим довше такий дозвіл залишається дійсним, тим довше існує можливість ним скористатися після моменту, для якого він був створений.
Тому для завантаження я прагну мати коротке вікно, достатнє для нормального початку операції, але не довше без потреби.
URL для читання має інший користувацький сценарій
Користувач може відкрити документ, дивитися відео, завантажувати файл або повернутися до вже відкритої сторінки через певний час.
Надто коротке вікно читання може створити зайві помилки навіть у нормальному сценарії.
Тому строк дії для читання може бути довшим за строк дії дозволу на запис, якщо це відповідає продукту і рівню чутливості файла.
Я визначаю відносне правило, а не універсальні цифри
Upload permission shorter window | venough to startthe intended write Read permission longer window | venough forthe intended viewingЯ не вважаю, що існує одна правильна кількість хвилин для всіх систем.
Розмір файла, швидкість мережі, спосіб використання, чутливість даних і можливість повторно запросити URL відрізняються між продуктами.
Натомість правило можна сформулювати стабільніше: дозвіл на запис має бути настільки коротким, наскільки дозволяє нормальний сценарій, а дозвіл на читання може враховувати реальну тривалість споживання файла.
Я не використовую одну змінну для обох сценаріїв
$expiresAt = now()->addMinutes( config('files.signed_url_minutes'),); $readUrl = Storage::disk('s3') ->temporaryUrl( $readPath, $expiresAt, ); $upload = Storage::disk('s3') ->temporaryUploadUrl( $uploadPath, $expiresAt, );Такий код технічно простий, але він створює небажаний зв’язок.
Якщо строк треба збільшити для довгого читання відео, автоматично збільшується і вікно запису.
Якщо строк скоротити через ризик завантаження, можна випадково погіршити нормальне читання великих файлів.
Це дві різні політики, тому я хочу бачити їх окремо.
У коді різниця має бути видимою
$uploadExpiresAt = now()->addMinutes( (int) config( 'files.upload_url_minutes', ),); $readExpiresAt = now()->addMinutes( (int) config( 'files.read_url_minutes', ),); $upload = Storage::disk('s3') ->temporaryUploadUrl( $uploadPath, $uploadExpiresAt,Тут навіть без знання конкретних значень видно, що система свідомо розрізняє два типи дозволу.
Це важливіше за саме число у конфігурації.
Наступний розробник не повинен здогадуватися, чи однаковий строк був випадковістю, історичною спадщиною або реальною вимогою.
Строк дії визначає сервер, а не клієнт
// Avoid this shape. $expiresIn = $request->integer( 'expiresIn',); $url = Storage::disk('s3') ->temporaryUrl( $path, now()->addSeconds( $expiresIn, ), );Браузер може повідомити, що хоче виконати певну операцію, але політика безпеки має залишатися на сервері.
Я не дозволяю клієнту довільно збільшувати строк підписаного URL.
Застосунок сам знає, який тип дозволу створює і яка політика до нього застосовується.
Короткий строк не виправляє неправильну перевірку прав
Дуже короткий URL усе одно небезпечний, якщо його видали не тому користувачу або не для того об’єкта.
Строк дії лише обмежує часовий інтервал уже виданого дозволу.
До створення URL застосунок все одно має перевірити право на читання або запис.
Строк дії також не є повноцінним механізмом відкликання
Після видачі підписаного URL сховище перевіряє його підпис і часові умови.
Якщо право користувача змінилося вже після видачі URL, старий URL не обов’язково дізнається про це миттєво.
Саме тому коротші вікна для більш ризикованих операцій корисні, але їх не варто плутати з повноцінним відкликанням доступу.
Прострочений URL для завантаження не потрібно продовжувати
upload URL expired | vclient asks application again | vauthorization again | vnew upload permissionЯкщо коротке вікно закрилося до початку завантаження, клієнт може запросити новий URL.
Для мене це кращий сценарій, ніж одразу видавати надто довгий дозвіл "про запас".
Новий запит знову проходить через застосунок, де можна повторно перевірити право і поточний стан ресурсу.
Для читання теж створюю новий URL після повторної перевірки
Постійно оновлювати стару підписану адресу на клієнті не потрібно.
Коли URL для читання більше не дійсний, клієнт звертається до застосунку по новий.
Це дає Laravel можливість ще раз перевірити, чи користувач досі має право на файл.
Навіть усередині читання може бути більше однієї політики
Не всі приватні файли однакові.
Відео, яке користувач дивиться в інтерфейсі, і короткий приватний документ можуть мати різний нормальний час використання.
Тому окрема політика для читання не обов’язково означає одне значення для кожного типу файла.
Головне, щоб відмінність випливала з реального сценарію і була визначена на сервері.
У журналах не варто зберігати повні підписані URL без потреби
Підписана адреса на час своєї дії є обліковими даними доступу.
Тому я не хочу без потреби записувати повний URL у прикладні журнали, повідомлення про помилки або аналітику.
Для діагностики зазвичай достатньо знати тип операції, шлях або внутрішній ідентифікатор, момент видачі та результат.
Я тестую політики окремо
Upload URL - authorized request receives URL- URL targets expected object key- expiration follows upload policy- expired permission is rejected- new permission requires application request Read URL - authorized request receives URL- URL targets expected object- expiration follows read policy- expired URL is rejected- fresh URL requires authorization againМій список перевірки для строку дії підписаного URL
Я перевіряю:
- Яку саме операцію дозволяє URL: читання чи запис?
- Чи строки для читання і запису визначені окремо?
- Чи дозвіл на запис не живе довше, ніж потребує нормальний сценарій?
- Чи читання має достатній час для реального використання файла?
- Чи строк визначає сервер, а не клієнт?
- Чи право перевіряється до створення URL?
- Чи новий URL після завершення строку вимагає нового звернення до застосунку?
- Чи повні підписані URL не потрапляють у журнали без потреби?
- Чи політики можна змінювати незалежно одна від одної?
Строк дії є частиною межі дозволу
Для мене різний строк дії URL для запису і читання не є дрібною оптимізацією.
Це спосіб явно показати, що система видає два різні дозволи з різним ризиком і різним нормальним часом використання.
URL для завантаження дає можливість записати дані, тому я тримаю його вікно коротшим. URL для читання може жити довше, якщо користувачу потрібен час, щоб нормально переглянути або завантажити файл.
При цьому жоден строк не замінює авторизацію і не перетворює підписаний URL на повноцінний механізм відкликання.
Час дії дозволу має відповідати дії, яку цей дозвіл відкриває.
Однаковий механізм підпису не означає однакову політику доступу. Читання і запис мають різний ризик, тому їхні часові межі теж можуть бути різними.



