Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як дозволити гостям частину дій у політиках Laravel і не відкрити зайвого?

За замовчуванням Laravel автоматично відмовляє неавтентифікованим користувачам у будь-якому гейті чи методі політики: метод навіть не викликається, а результат - false. Це безпечне значення за замовчуванням.

Щоб гість міг пройти перевірку, параметр користувача оголошують необов'язковим:

class PostPolicy
{
    public function view(?User $user, Post $post): bool
    {
        if ($post->is_published) {
            return true;   // опубліковане бачать усі, включно з гостями
        }

        return $user !== null && $user->id === $post->author_id;   // чернетку - лише автор
    }
}
Gate::define('view-pricing', fn (?User $user) => true);

Типові сценарії:

  • публічний перегляд опублікованих матеріалів і приватний - чернеток;
  • каталог для всіх, а ціни для партнерів - лише після входу;
  • форма зворотного зв'язку для гостей з обмеженням частоти.

Пастки:

1. ?User і забута перевірка на null:

public function view(?User $user, Post $post): bool
{
    return $user->id === $post->author_id || $post->is_published;   // помилка для гостя
}

Для гостя $user->id - звернення до властивості null: у PHP 8 це помилка (Attempt to read property "id" on null), а не false. Завжди перевіряти null першим.

2. Гостьовий доступ, відкритий занадто широко. Додали ?User у view, щоб показувати опубліковані пости, - і забули, що той самий метод використовується для перегляду чернеток у прев'ю. Кожен метод з ?User варто переглядати окремо: які гілки повертають true для гостя.

3. Неявна довіра до параметрів: «опубліковане» має визначатися полем у базі (is_published), а не параметром запиту (?preview=1).

4. Авторизація ≠ автентифікація маршруту. Middleware auth на маршруті відсіює гостей ще до політики. Якщо маршрут має бути доступним гостям частково, auth на ньому не ставлять, а розрізнення робить політика.

Тести для гостьових сценаріїв: перевірити, що гість бачить лише дозволене ($this->get(...)->assertOk() для опублікованого, assertForbidden()/assertNotFound() для чернетки), - саме тут найчастіше випадково відкривають приватні дані.

Докладніше в документації: Laravel: гості в авторизації

Схожі питання