Безопасность - это серьезное дело, когда речь идет о веб-приложениях. Вы хотите быть уверены, что ваше приложение безопасно и данные ваших пользователей защищены. Flight предоставляет ряд функций, чтобы помочь вам обеспечить безопасность ваших веб-приложений.
HTTP заголовки - один из самых простых способов защитить ваши веб-приложения. Вы можете использовать заголовки, чтобы предотвратить clickjacking, XSS и другие атаки. Есть несколько способов, как можно добавить эти заголовки к вашему приложению.
Два отличных сайта, на которых можно проверить безопасность ваших заголовков, это securityheaders.com и observatory.mozilla.org.
Вы можете вручную добавить эти заголовки, используя метод 'header' объекта Flight\Response.
Flight\Response
// Установить заголовок X-Frame-Options для предотвращения clickjacking Flight::response()->header('X-Frame-Options', 'SAMEORIGIN'); // Установить заголовок Content-Security-Policy для предотвращения XSS // Примечание: этот заголовок может быть очень сложным, так что вам понадобится // обращаться к примерам в интернете для вашего приложения Flight::response()->header("Content-Security-Policy", "default-src 'self'"); // Установить заголовок X-XSS-Protection для предотвращения XSS Flight::response()->header('X-XSS-Protection', '1; mode=block'); // Установить заголовок X-Content-Type-Options для предотвращения MIME sniffing Flight::response()->header('X-Content-Type-Options', 'nosniff'); // Установить заголовок Referrer-Policy для управления количеством отправляемой информации обратного адреса Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade'); // Установить заголовок Strict-Transport-Security для принудительного использования HTTPS Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload'); // Установить заголовок Permissions-Policy для управления используемыми функциями и API Flight::response()->header('Permissions-Policy', 'geolocation=()');
Эти заголовки могут быть добавлены в начало ваших файлов bootstrap.php или index.php.
bootstrap.php
index.php
Вы также можете добавить их в фильтр/хук, как показано ниже:
// Добавить заголовки в фильтр Flight::before('start', function() { Flight::response()->header('X-Frame-Options', 'SAMEORIGIN'); Flight::response()->header("Content-Security-Policy", "default-src 'self'"); Flight::response()->header('X-XSS-Protection', '1; mode=block'); Flight::response()->header('X-Content-Type-Options', 'nosniff'); Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade'); Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload'); Flight::response()->header('Permissions-Policy', 'geolocation=()'); });
Вы также можете добавить их как класс Middleware. Это хороший способ держать свой код чистым и организованным.
// app/middleware/SecurityHeadersMiddleware.php namespace app\middleware; class SecurityHeadersMiddleware { public function before(array $params): void { Flight::response()->header('X-Frame-Options', 'SAMEORIGIN'); Flight::response()->header("Content-Security-Policy", "default-src 'self'"); Flight::response()->header('X-XSS-Protection', '1; mode=block'); Flight::response()->header('X-Content-Type-Options', 'nosniff'); Flight::response()->header('Referrer-Policy', 'no-referrer-when-downgrade'); Flight::response()->header('Strict-Transport-Security', 'max-age=31536000; includeSubDomains; preload'); Flight::response()->header('Permissions-Policy', 'geolocation=()'); } } // index.php или где у вас находятся ваши маршруты //FYI, эта группа пустых строк действует как глобальное промежуточное ПО для всех маршрутов. Конечно же, вы могли бы сделать то же самое и просто добавить это только к определенным маршрутам. Flight::group('', function(Router $router) { $router->get('/users', [ 'UserController', 'getUsers']); // более маршрутов }, [ new SecurityHeadersMiddleware() ]);
Межсайтовая подделка запроса (CSRF) - это тип атаки, при которой злоумышленный сайт может заставить браузер пользователя отправить запрос на ваш сайт. Это может использоваться для выполнения действий на вашем сайте без ведома пользователя. Flight не предоставляет встроенного механизма защиты от CSRF, но вы легко можете реализовать свой собственный, используя промежуточное программное обеспечение.
Сначала вам необходимо сгенерировать токен CSRF и сохранить его в сессии пользователя. Затем вы можете использовать этот токен в ваших формах и проверять его при отправке формы.
// Сгенерировать токен CSRF и сохранить его в сессии пользователя // (предполагая, что вы создали объект сеанса и присоединили его к Flight) // см. документацию по сессиям для получения дополнительной информации Flight::register('session', \Ghostff\Session\Session::class); // Вам нужно сгенерировать только один токен на сеанс (чтобы он работал // в нескольких вкладках и запросах для одного и того же пользователя) if(Flight::session()->get('csrf_token') === null) { Flight::session()->set('csrf_token', bin2hex(random_bytes(32)) ); }
<!-- Используйте токен CSRF в вашей форме --> <form method="post"> <input type="hidden" name="csrf_token" value="<?= Flight::session()->get('csrf_token') ?>"> <!-- другие поля формы --> </form>
Вы также можете установить пользовательскую функцию для вывода токена CSRF в ваших шаблонах Latte.
// Установить пользовательскую функцию для вывода токена CSRF // Примечание: Вид был настроен с движком представления Latte Flight::view()->addFunction('csrf', function() { $csrfToken = Flight::session()->get('csrf_token'); return new \Latte\Runtime\Html('<input type="hidden" name="csrf_token" value="' . $csrfToken . '">'); });
И теперь в ваших шаблонах Latte вы можете использовать функцию csrf() для вывода токена CSRF.
csrf()
<form method="post"> {csrf()} <!-- другие поля формы --> </form>
Коротко и просто, верно?
Вы можете проверить токен CSRF, используя фильтры событий:
// Это промежуточное программное обеспечение проверяет, является ли запрос запросом POST, и если да, проверяет, является ли токен CSRF допустимым Flight::before('start', function() { if(Flight::request()->method == 'POST') { // получаем токен CSRF из значений формы $token = Flight::request()->data->csrf_token; if($token !== Flight::session()->get('csrf_token')) { Flight::halt(403, 'Недопустимый токен CSRF'); // или для JSON-ответа Flight::jsonHalt(['error' => 'Недопустимый токен CSRF'], 403); } } });
Или вы можете использовать класс промежуточного программного обеспечения:
// app/middleware/CsrfMiddleware.php namespace app\middleware; class CsrfMiddleware { public function before(array $params): void { if(Flight::request()->method == 'POST') { $token = Flight::request()->data->csrf_token; if($token !== Flight::session()->get('csrf_token')) { Flight::halt(403, 'Недопустимый токен CSRF'); } } } } // index.php или где у вас находятся ваши маршруты Flight::group('', function(Router $router) { $router->get('/users', [ 'UserController', 'getUsers' ]); // более маршрутов }, [ new CsrfMiddleware() ]);
Межсайтовая вставка скриптов (XSS) - это тип атаки, при которой злоумышленный сайт может внедрить код на вашем сайте. Большинство таких возможностей происходят из значений форм, которые вводят ваши конечные пользователи. Никогда не доверяйте выводу от ваших пользователей! Всегда предполагайте, что все они - лучшие хакеры в мире. Они могут внедрить вредоносный JavaScript или HTML на вашу страницу. Этот код может использоваться для кражи информации от ваших пользователей или выполнения действий на вашем сайте. Используя класс представлений Flight, вы легко можете экранировать вывод для предотвращения атак XSS.
// Допустим, пользователь умный и пытается использовать это в качестве своего имени $name = '<script>alert("XSS")</script>'; // Это экранирует вывод Flight::view()->set('name', $name); // Это выведет: <script>alert("XSS")</script> // Если вы используете что-то вроде Latte, зарегистрированного как ваш класс представлений, он также автоматически будет экранировать это. Flight::view()->render('template', ['name' => $name]);
SQL инъекция - это тип атаки, при которой злоумышленный пользователь может внедрить SQL-код в вашу базу данных. Это может быть использовано для кражи информации из вашей базы данных или выполнения действий над вашей базой данных. Опять же, никогда не доверяйте вводу от ваших пользователей! Всегда предполагайте, что они настроены враждебно. Вы можете использовать подготовленные операторы в ваших объектах PDO, чтобы предотвратить SQL инъекцию.
PDO
// Предполагая, что у вас зарегистрирован Flight::db() как ваш объект PDO $statement = Flight::db()->prepare('SELECT * FROM users WHERE username = :username'); $statement->execute([':username' => $username]); $users = $statement->fetchAll(); // Если вы используете класс PdoWrapper, это можно сделать легко в одной строке $users = Flight::db()->fetchAll('SELECT * FROM users WHERE username = :username', [ 'username' => $username ]); // Вы можете сделать то же самое с объектом PDO с использованием плейсхолдеров ? $statement = Flight::db()->fetchAll('SELECT * FROM users WHERE username = ?', [ $username ]); // Просто пообещайте, что вы никогда, никогда НИКОГДА не сделаете что-то подобное... $users = Flight::db()->fetchAll("SELECT * FROM users WHERE username = '{$username}' LIMIT 5"); // потому что что, если $username = "' OR 1=1; -- "; // После построения запроса он выглядит следующим образом // SELECT * FROM users WHERE username = '' OR 1=1; -- LIMIT 5 // Это выглядит странно, но это действующий запрос, который будет работать. Фактически, // это очень распространенная атака методом SQL инъекции, которая вернет все пользователей.
Обмен ресурсами между разными источниками (CORS) - это механизм, который позволяет запросить множество ресурсов (например, шрифты, JavaScript и т. д.) на веб-странице из другого домена, отличного от домена, из которого ресурс был запрошен. У Flight нет встроенной функциональности, но это легко можно обработать с помощью хука, который запускается перед вызовом метода Flight::start().
Flight::start()
// app/utils/CorsUtil.php namespace app\utils; class CorsUtil { public function set(array $params): void { $request = Flight::request(); $response = Flight::response(); if ($request->getVar('HTTP_ORIGIN') !== '') { $this->allowOrigins(); $response->header('Access-Control-Allow-Credentials', 'true'); $response->header('Access-Control-Max-Age', '86400'); } if ($request->method === 'OPTIONS') { if ($request->getVar('HTTP_ACCESS_CONTROL_REQUEST_METHOD') !== '') { $response->header( 'Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH, OPTIONS, HEAD' ); } if ($request->getVar('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') !== '') { $response->header( "Access-Control-Allow-Headers", $request->getVar('HTTP_ACCESS_CONTROL_REQUEST_HEADERS') ); } $response->status(200); $response->send(); exit; } } private function allowOrigins(): void { // настройте разрешенные хосты здесь $allowed = [ 'capacitor://localhost', 'ionic://localhost', 'http://localhost', 'http://localhost:4200', 'http://localhost:8080', 'http://localhost:8100', ]; $request = Flight::request(); if (in_array($request->getVar('HTTP_ORIGIN'), $allowed, true) === true) { $response = Flight::response(); $response->header("Access-Control-Allow-Origin", $request->getVar('HTTP_ORIGIN')); } } } // index.php или где у вас находятся ваши маршруты $CorsUtil = new CorsUtil(); // Это должно быть выполнено до вызова start. Flight::before('start', [ $CorsUtil, 'setupCors' ]);
Безопасность - это серьезное дело, и важно, чтобы ваши веб-приложения были безопасны. Flight предоставляет ряд функций, чтобы помочь вам обеспечить безопасность ваших веб-приложений, но важно всегда быть бдительным и удостовериться, что вы делаете все возможное, чтобы сохранить безопасность данных ваших пользователей. Всегда предполагайте худшее и никогда не доверяйте вводу от ваши# Безопасность
// app/middleware/CsrfMiddleware.php namespace app\middleware; class CsrfMiddleware { public function before(array $params): void { if(Flight::request()->method == 'POST') { $token = Flight::request()->data->csrf_token; if($token !== Flight::session()->get('csrf_token')) { Flight::halt(403, 'Недопустимый токен CSRF'); } } } } // index.php или где у вас находятся ваши маршруты Flight::group('', function(Router $router) { $router->get('/users', [ 'UserController', 'getUsers']); // более маршрутов }, [ new CsrfMiddleware() ]);
Межсайтовая вставка скриптов (XSS) - это тип атаки, при которой злоумышленный сайт может внедрить код на вашем сайте. Большинство таких возможностей происходят из значений форм, которые вводят ваши конечные пользователи. Никогда не доверяйте выводу от ваших пользователей! Всегда предполагайте, что все они - лучшие хакеры в мире. Они могут внедрить вредоносный JavaScript или HTML на вашу страницу. Этот код может быть использован для кражи информации от ваших пользователей или выполнения действий на вашем сайте. Используя класс представлений Flight, вы легко можете экранировать вывод для предотвращения атак XSS.
SQL инъекция - это тип атаки, при которой злоумышленный пользователь может внедрить SQL-код в вашу базу данных. Это может быть использовано для кражи информации из вашей базы данных или выполнения действий над вашей базой данных. Опять же, никогда не доверяйте вводу от ваших пользователей! Всегда предполагайте они нацелены на вас. Вы можете использовать подготовленные операторы в ваших объектах PDO, чтобы предотвратить SQL инъекцию.
Безопасность - это серьезное дело, и важно, чтобы ваши веб-приложения были безопасны. Flight предоставляет ряд функций, чтобы помочь вам обеспечить безопасность ваших веб-приложений, но важно всегда быть бдительным и удостовериться, что вы делаете все возможное, чтобы сохранить безопасность данных ваших пользователей. Всегда предполагайте худшее и никогда не доверяйте вводу от ваши