Як розміщувати статичні файли на CDN за допомогою Casdoor: S3, MinIO, Azure Blob та інші провайдери сховища
Щоб розміщувати статичні файли на CDN, помістіть їх у сховище об'єктів (Amazon S3, MinIO, Azure Blob Storage, Google Cloud Storage, Alibaba Cloud OSS або Tencent Cloud COS), зробіть так, щоб CDN витягував дані з цього бакета як свого origin, і надавайте URL-адреси на домені CDN. У Casdoor це один параметр: створіть провайдера сховища для бакета та вкажіть адресу CDN у його полі Domain. Casdoor завантажує аватари та інші файли через API провайдера та зберігає URL-адреси, що починаються з цього домену. Інтерфейс самого Casdoor також може подаватися з CDN через frontendCdnUrl та staticBaseUrl у app.conf.
Провайдери сховища в загальному вигляді
Провайдер сховища визначає, куди Casdoor записує завантажені файли: аватари користувачів, зображення ID-карток, сторінки умов використання та будь-що, завантажене на сторінці Resources. Ви додаєте провайдера до додатка, і завантаження в цьому додатку йдуть до нього. Огляд провайдерів сховища перелічує всі типи. Ця таблиця охоплює ті, які найчастіше цікавлять:
| Сховище | Тип провайдера Casdoor | Чи використовує Casdoor S3 API? | Можна розмістити самостійно | Як встановлюється публічна URL-адреса |
|---|---|---|---|---|
| Локальна файлова система | Local File System | Ні, звичайні файли на диску | Так, це сервер Casdoor | Обслуговується Casdoor за адресою /files/. Поле Domain доступне лише для читання |
| Amazon S3 | AWS S3 | Так | Ні | Domain: URL-адреса бакета або домен CloudFront. Endpoint (Intranet): кінцева точка VPC |
| MinIO | MinIO | Так, із запитами path-style | Так | Domain: URL-адреса MinIO, за якою слідує ім'я бакета, або домен CDN |
| Alibaba Cloud OSS | Aliyun OSS | Ні, SDK OSS | Ні | Domain: домен CDN. Якщо залишити порожнім, стане bucket.endpoint. Endpoint (Intranet): внутрішня кінцева точка |
| Tencent Cloud COS | Tencent Cloud COS | Ні, API COS | Ні | Domain: домен CDN |
| Azure Blob Storage | Azure Blob | Ні, API Blob | Ні | Domain: власний домен або домен Front Door. Casdoor додає ім'я контейнера до шляху |
| Google Cloud Storage | Google Cloud Storage | Ні, Go-клієнт Google | Ні | Domain: якщо залишити порожнім, стає https://storage.googleapis.com. Casdoor додає ім'я бакета до шляху |
| NAS Synology | Synology | Ні, API DSM File Station | Так | Немає поля Domain. URL-адреса базується на Endpoint |
Casdoor також підтримує Qiniu Cloud Kodo, CUCloud OSS та Casdoor, який зберігає файли в іншому екземплярі Casdoor. Посібники для окремих провайдерів — Amazon S3, MinIO, Azure Blob, Google Cloud Storage, Alibaba Cloud OSS, Tencent Cloud COS, NAS Synology та локальна файлова система — показують, яке значення в якому полі вказати.
Endpoint проти Domain
Ці два поля виконують різні завдання, і більшість проблем із CDN виникають через їх плутанину.
- Endpoint — це адреса, яку Casdoor використовує для спілкування з API сховища: завантаження, видалення, перегляд списку. CDN тут не задіяний.
- Endpoint (Intranet) замінює Endpoint, коли в
app.confвстановленоisCloudIntranet = true. Це дозволяє утримувати трафік завантаження в межах внутрішньої мережі провайдера, коли Casdoor працює в тій самій хмарі. Це поле доступне для AWS S3, Aliyun OSS, Azure Blob та CUCloud OSS. - Domain — це база URL-адреси, яку зберігає Casdoor і яку запитують браузери. Якщо у вас є CDN, його домен потрібно вказати тут.
- Path prefix додається на початку кожного ключа об'єкта. З префіксом
casdoorаватар буде збережено за шляхомcasdoor/avatar/....
Casdoor формує URL-адресу файлу зі схеми та хоста Domain, потім шляху Domain, потім префіксу шляху, а потім шляху до файлу. Домен без схеми отримує префікс https://. Шляхова частина Domain також стає частиною ключа об'єкта, тому https://cdn.example.com/casdoor/ зберігає файли в директорії casdoor/ у бакеті. Для Azure Blob та Google Cloud Storage Casdoor додає ім'я контейнера або бакета як перший сегмент шляху після хоста. Ваш CDN повинен обслуговувати цей шлях.
Якщо Domain порожній, Casdoor заповнює його з ендпоінту провайдера при першому використанні провайдера та зберігає це значення. Іноді результат працює, як у випадку з OSS та GCS. Іноді ні: для ендпоінту S3 без імені бакета або для MinIO, де запити path-style розміщують ім'я бакета в шляху, згенерована URL-адреса не містить бакета. Вкажіть Domain вручну, завантажте один тестовий аватар і відкрийте URL-адресу, яку повернув Casdoor, перш ніж цим скористаються інші.
Провайдер, який Casdoor використовує для аватарів, скопійованих із соціальних логінів, визначається параметром defaultStorageProvider у app.conf. Це ім'я провайдера, що належить admin (див. довідник конфігурації):
defaultStorageProvider = provider_storage_s3
isCloudIntranet = false
Публічні бакети, приватні бакети та підписані URL-адреси
Casdoor зберігає одну просту, постійну URL-адресу в полі avatar користувача та в записі ресурсу. Він не створює підписані або термінові URL-адреси для цих файлів. Тому все, що знаходиться за адресою Domain, повинно відповідати на анонімний запит GET. Є два способи зробити це.
Зробіть об'єкти публічними. Для AWS S3 та MinIO Casdoor завантажує кожен об'єкт із канонічним ACL public-read. Для Aliyun OSS клієнтська бібліотека робить те саме за замовчуванням. У S3 це конфліктує з налаштуваннями нових бакетів за замовчуванням: згідно з AWS, нові бакети використовують налаштування Bucket owner enforced, яке вимикає ACL, і завантаження, що встановлює ACL на кшталт public-read, завершується помилкою AccessControlListNotSupported. Саме тому в посібнику Amazon S3 рекомендується увімкнути ACL та вимкнути Block all public access. В OSS ACL об'єкта має перевагу над ACL бакета, тому об'єкт public-read можна прочитати навіть у приватному бакеті. MinIO не використовує ACL для анонімного читання. Він використовує політику бакета:
mc anonymous set download myminio/casdoor
Azure потребує дозволу анонімного доступу на рівні облікового запису сховища та встановлення рівня доступу контейнера на Blob. Google Cloud Storage потребує надання ролі Storage Object Viewer (roles/storage.objectViewer) для allUsers на рівні бакета.
Залиште бакет приватним і дозвольте читати його лише через CDN. CDN підписує свої запити до origin-сервера, а переглядачі отримують доступ через CDN без підпису. Кожен вендор має свою версію цього рішення:
- CloudFront має контроль доступу до origin (OAC). AWS вимагає Bucket owner enforced для OAC, або Bucket owner preferred, якщо вам потрібні ACL.
- Alibaba Cloud CDN може отримувати дані з приватного бакета OSS після авторизації.
- Tencent Cloud CDN має автентифікацію origin-pull для приватних бакетів COS.
- Azure Front Door Premium може отримувати доступ до облікового запису сховища через Private Link.
- Посібник Google Cloud CDN також охоплює доступ до приватних бакетів, де роль Storage Object Viewer надається сервісному обліковому запису замість
allUsers.
Це приховує власну URL-адресу бакета, але файли залишаються публічно доступними через CDN. Для типів AWS S3 та Aliyun OSS об'єкти також залишаються доступними для читання за їхніми URL-адресами бакета через ACL public-read, який встановлює Casdoor.
Якщо аватари взагалі не повинні бути публічними, CDN перед сховищем об'єктів — неправильний інструмент. Зберігайте ці файли на керованому вами типі сховища та обмежуйте коло осіб, які можуть отримати доступ до цього хоста.
Заголовки кешування та проблема з аватарами
У S3 та MinIO Casdoor встановлює Content-Type на основі розширення файлу під час завантаження. Він не встановлює Cache-Control жодному провайдеру. Це означає, що діє TTL CDN за замовчуванням. У CloudFront об'єкти без Cache-Control кешуються на TTL за замовчуванням, який становить 24 години, якщо ви не використовуєте політику кешування. Щоб контролювати це для кожного об'єкта, додайте метадані Cache-Control у бакеті. Для всього шляху використовуйте правило кешування на рівні CDN.
Аватари потребують короткого TTL. Коли користувач змінює своє зображення, Casdoor записує новий файл за тим самим ключем avatar/<organization>/<username>.<extension> та зберігає ту саму URL-адресу. Довгий TTL означає, що люди бачитимуть старе зображення, доки воно не застаріє або доки ви не очистите чи не скасуєте кешування цього шляху. Інші завантаження отримують числовий суфікс (-1, -2, ...), якщо ім'я вже зайняте, тому нове завантаження отримує нову URL-адресу і може кешуватися довго.
Робоча схема:
| Шлях | Рекомендоване кешування |
|---|---|
avatar/* | Короткий TTL (хвилини) або очищення кешу при зміні |
resource/* та інші завантаження | Довгий TTL |
Хешовані фронтенд-ресурси (assets/*) | Дуже довгий TTL. Ім'я файлу змінюється при кожній збірці |
Власний фронтенд Casdoor на CDN
Окремо від завантажень користувачів, існує три способи перенести власні статичні файли Casdoor з сервера Casdoor.
frontendCdnUrl. Використовуйте цей параметр, якщо ви встановлюєте фронтенд з npm-пакета casdoor-web. Вкажіть на нього npm CDN, наприклад:
frontendCdnUrl = "https://cdn.jsdelivr.net/npm/{name}@{version}"
Casdoor читає назву пакета та версію з package.json у папці збірки. Він переписує посилання на скрипти та стилі в index.html на цей CDN і зберігає локальні шляхи як резервний варіант. Якщо файл не вдається завантажити, браузер завантажує його з Casdoor, а cookie утримує цей браузер на локальних файлах до кінця сесії. Фронтенд, зібраний вами вручну, не має такого package.json, тому ця настройка на нього не впливає.
Скрипт розгортання. Для фронтенду, який ви збираєте з вихідного коду, у статті Розміщення файлів фронтенду на CDN пояснюється робота deployment/deploy_test.go. Він завантажує web/build/assets/ через один із ваших постачальників сховища та вказує index.html на Domain постачальника, який має закінчуватися на /. Vite хешує ці імена файлів, тому вони підходять для довгого TTL, зазначеного в таблиці вище.
staticBaseUrl. Визначає, звідки надходять зображення за замовчуванням, такі як логотипи, іконки провайдерів та аватар за замовчуванням. За замовчуванням використовується https://cdn.casbin.org, який обслуговує репозиторій casbin/static. У мережі без доступу до Інтернету розмістіть власну копію цього репозиторію та вкажіть staticBaseUrl на неї, як описано в Розміщення статичних файлів у внутрішній мережі.
Вибір одного варіанту
- Один сервер, мала база користувачів:
Local File System. Змонтируйте каталогfilesна том, якщо Casdoor працює в контейнері. Casdoor надсилаєX-Content-Type-Options: nosniffта пісочницюContent-Security-Policyдля цих файлів, тому завантажений HTML- або SVG-файл не може виконувати скрипти на вашому домені Casdoor. - Self-hosted та сумісний із S3:
MinIO. Це також тип, який документація рекомендує для інших сховищ, сумісних із S3. - Вже використовуєте хмару: скористайтеся об'єктним сховищем та CDN цієї хмари, вкажіть Endpoint (Intranet), де Casdoor працює в тій самій хмарі, а Domain — на CDN.
Посилання
- Постачальники сховища Casdoor та вихідний код:
object/storage.go,storage/,routers/frontend_cdn.go - AWS: Керування володінням об'єктами та відключення ACL, Обмеження доступу до джерела Amazon S3, Управління часом перебування контенту в кеші
- MinIO:
mc anonymous set - Microsoft: Налаштування анонімного доступу на читання для контейнерів та блобів, Інтеграція облікового запису Azure Storage з Azure Front Door
- Google Cloud: Зробити дані публічними, Налаштування Cloud CDN із backend bucket
- Alibaba Cloud: Object ACL, Отримання з приватних бакетів OSS
- Tencent Cloud: Налаштування прискорення CDN для COS