Сборка CSP⚓︎
Livewire предлагает CSP-безопасную сборку, которая позволяет использовать приложения Livewire в средах со строгими заголовками политики безопасности контента (CSP), запрещающими 'unsafe-eval'.
Что такое политика безопасности контента (CSP)?⚓︎
Политика безопасности контента (CSP) — это стандарт безопасности, помогающий предотвратить различные типы атак, включая межсайтовый скриптинг (XSS) и атаки с внедрением кода. CSP работает, позволяя веб-разработчикам контролировать, какие ресурсы браузеру разрешено загружать и выполнять.
Одной из самых строгих директив CSP является 'unsafe-eval'. Если она опущена, это предотвращает выполнение JavaScript-кода динамически через такие функции, как eval(), new Function() и аналогичные конструкции, которые компилируют и выполняют строки как код во время выполнения.
Почему CSP влияет на Livewire⚓︎
По умолчанию Livewire (и лежащий в его основе фреймворк Alpine.js) использует объявления new Function() для компиляции и выполнения JavaScript-выражений из атрибутов HTML, таких как:
<button wire:click="$set('count', count + 1)">Увеличить</button>
<div wire:show="user.role === 'admin'">Админка</div>
Хотя этот подход намного быстрее и безопаснее, чем прямое использование eval(), он всё же нарушает директиву CSP 'unsafe-eval', которую применяют многие приложения, заботящиеся о безопасности.
Включение CSP-безопасного режима⚓︎
Чтобы включить CSP-безопасный режим Livewire, вам необходимо изменить конфигурацию вашего приложения:
Конфигурация⚓︎
В файле config/livewire.php установите параметр csp_safe в значение true:
Влияние на Alpine.js⚓︎
Важно: когда вы включаете CSP-безопасный режим в Livewire, это также влияет на всю функциональность Alpine.js в вашем приложении. Alpine автоматически начнет использовать свой CSP-безопасный вычислитель, что означает, что все выражения Alpine в вашем приложении будут подчиняться тем же ограничениям синтаксического анализа.
Именно здесь большинство разработчиков заметят ограничения, так как выражения Alpine, как правило, сложнее типичных выражений Livewire.
Что поддерживается⚓︎
Сборка CSP поддерживает большинство распространённых выражений JavaScript, которые вы используете в Livewire:
Базовые выражения Livewire⚓︎
<!-- Это работает -->
<button wire:click="increment">+</button>
<button wire:click="decrement">-</button>
<button wire:click="reset">Сброс</button>
<button wire:click="save">Сохранить</button>
<input wire:model="name">
<input wire:model.live="search">
Вызовы методов с параметрами⚓︎
<!-- Это работает -->
<button wire:click="updateUser('John', 25)">Обновить данные пользователя</button>
<button wire:click="setCount(42)">Установить счётчик</button>
<button wire:click="saveData({ name: 'John', age: 30 })">Сохранить объект</button>
Доступ к свойствам и их обновление⚓︎
<!-- Это работает -->
<input wire:model="user.name">
<input wire:model="settings.theme">
<button wire:click="$set('user.active', true)">Активировать</button>
<div wire:show="user.role === 'admin'">Админка</div>
Базовые выражения в Alpine⚓︎
<!-- Это работает -->
<div x-data="{ count: 0, name: 'Livewire' }" wire:ignore>
<button x-on:click="count++">Увеличить</button>
<span x-text="count"></span>
<span x-text="'Привет, ' + name"></span>
<div x-show="count > 5">Число больше 5!</div>
</div>
Что не поддерживается⚓︎
Некоторые расширенные возможности JavaScript не будут работать в CSP-безопасном режиме:
Сложные JavaScript-выражения⚓︎
<!-- Это не работает -->
<button wire:click="items.filter(i => i.active).length">Подсчёт только активных?</button>
<div wire:show="users.some(u => u.role === 'admin')">Есть права админа?</div>
<button wire:click="(() => console.log('Hi'))()">Сложная функция</button>
Шаблонные литералы и расширенный синтаксис⚓︎
<!-- Это не работает -->
<div x-text="`Hello ${name}`">Плохо</div>
<div x-data="{ ...defaults }">Плохо</div>
<button x-on:click="() => doSomething()">Плохо</button>
Динамический доступ к свойствам⚓︎
<!-- Это не работает -->
<div wire:show="user[dynamicProperty]">Плохо</div>
<button wire:click="this[methodName]()">Плохо</button>
Обход ограничений⚓︎
Для сложных выражений Alpine используйте Alpine.data() или перенесите логику в методы:
<!-- Вместо сложных встроенных выражений -->
<div x-data="users">
<div x-show="hasActiveAdmins">Админка доступна</div>
<span x-text="activeUserCount">0</span>
</div>
<script nonce="[nonce]">
Alpine.data('users', () => ({
users: ...,
get hasActiveAdmins() {
return this.users.filter(u => u.active && u.role === 'admin').length > 0;
},
get activeUserCount() {
return this.users.filter(u => u.active).length;
}
}));
</script>
Пример заголовков CSP⚓︎
Вот пример заголовков CSP, которые работают с CSP-безопасной сборкой Livewire:
Content-Security-Policy: default-src 'self';
script-src 'nonce-[random]' 'strict-dynamic';
style-src 'self' 'unsafe-inline';
Ключевые моменты:
- Удалите
'unsafe-eval'из директивыscript-src - Используйте загрузку скриптов на основе nonce с
'nonce-[random]' - Рассмотрите возможность добавления
'strict-dynamic'для лучшей совместимости с динамически загружаемыми скриптами
Рекомендации по производительности⚓︎
CSP-безопасная сборка использует другой вычислитель выражений, который:
- Парсинг: чуть более медленный начальный парсинг выражений (обычно незначительно)
- Время выполнения: аналогичная производительность во время выполнения для простых выражений
- Размер бандла: немного больший размер JavaScript-бандла из-за кастомного парсера
Для большинства приложений эти различия незаметны, но стоит провести тестирование в вашем конкретном случае.
Тестирование вашей реализации CSP⚓︎
Чтобы убедиться, что ваша настройка CSP работает:
- Включите заголовки CSP на вашем веб-сервере или в приложении
- Проверьте в инструментах разработчика браузера — нарушения CSP появятся в консоли
- Убедитесь, что выражения работают — все ваши выражения Livewire и Alpine должны функционировать нормально
- Проверьте на наличие ошибок в консоли — не должно появляться никаких нарушений
unsafe-eval
Когда использовать CSP-безопасный режим⚓︎
Рассмотрите возможность использования CSP-безопасного режима, когда:
- Ваше приложение требует строгого соответствия CSP
- Вы создаете приложения для сред с высокими требованиями к безопасности
- Политики безопасности вашей организации запрещают
'unsafe-eval' - Вы развёртываете приложение на платформах с обязательными ограничениями CSP