APP_KEY - головний секрет застосунку. Ним Laravel шифрує й підписує дані, що залишають сервер чи зберігаються:
- cookie: сесійна cookie й інші cookie, які шифрує middleware
EncryptCookies; - сесії (якщо
SESSION_ENCRYPT=true); - підписані URL (
URL::signedRoute, посилання підтвердження email); - дані, зашифровані через
Cryptта кастиencryptedу моделях; - сторонні механізми, що на нього спираються (наприклад, підпис знімків стану Livewire).
Генерується командою php artisan key:generate (AES-256, 32 байти, у .env як base64:...).
Чому ключ не можна просто замінити: після зміни все, що зашифровано старим ключем, перестає розшифровуватися:
- користувачі розлогінюються (cookie недійсні);
- посилання з листів (підтвердження, скидання) перестають працювати;
- дані в базі з кастом
encryptedстають нечитабельними - це найнебезпечніше.
Плавна ротація: старі ключі перелічуються в APP_PREVIOUS_KEYS:
APP_KEY=base64:новий...
APP_PREVIOUS_KEYS=base64:старий...
Laravel шифрує лише новим ключем, а розшифровує - пробуючи поточний і попередні. Користувачі не розлогінюються, старі посилання діють.
Повна ротація (наприклад, після витоку ключа):
- новий ключ у
APP_KEY, старий - уAPP_PREVIOUS_KEYS; - перешифрувати дані в базі новим ключем (команда, що читає й зберігає кожне зашифроване поле);
- через час, достатній для завершення сесій і закінчення терміну посилань, прибрати старий ключ з
APP_PREVIOUS_KEYS.
Правила зберігання:
- у
.envчи менеджері секретів, ніколи в репозиторії; - різні ключі для середовищ (локальне, тестове, продакшен) - інакше cookie з тестового стенда підходять до продакшену;
- однаковий ключ на всіх серверах одного середовища - інакше сесії «ламаються» при переході між серверами за балансувальником;
- при підозрі на витік - ротація і перешифрування.
Не плутати з хешуванням паролів: паролі хешуються (bcrypt/argon2) без APP_KEY - зміна ключа на них не впливає.
Докладніше в документації: Laravel: ротація ключів шифрування