@betterthanyouthink
Начинающий программист :)

Как сделать роутинг на чистом php, перенаправляя абсолютно все запросы в index.php?

Пишу сайт на чистом php, столкнулся с роутингом. Проблема в следующем: .htaccess перенаправляет не все запросы в index.php. К примеру, запросы типа site.com, site.com/about, site.com/offers он обрабатывает корректно, но если ввести в url строку подпапку + существующий файл, то запрос не будет перенаправлен в index.php и файл откроется.

Т.е. запрос site.com/components/test.php - не будет обработан и страница будет показана юзеру. При этом, если ввести несуществующий запрос c той же подпапкой, то запрос обработается корректно: site.com/components/test_1.php - перенаправит на страницу 404.

С одной стороны, меня такое поведение устраивает, потому что у меня проходят все ajax запросы без дополнительной обработки маршрутов. Но, с другой стороны, я думаю, что это плохо с точки зрения безопасности. Подскажите, как сделать правильно или в какую сторону копать. На ларавель планирую пересесть, как только закончу свой проект на чистом php :)

.htaccess
AddDefaultCharset UTF-8
RewriteEngine on
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) /index.php [QSA,L]


index.php

//url
$request_url = rtrim(ltrim(urldecode(parse_url($_SERVER['REQUEST_URI'],5)), '/'), '/');
$params = array_filter(explode("/", $request_url)); 
//если в url передано 2 параметра
if (count($params) == 2) {
    $dynamic_routes = [
        'offers' =>  'pages/offer.php',
    ];
    if (isset($dynamic_routes[$params[0]])) {
        $get = $params[1];
        require_once $dynamic_routes[$params[0]];
    }
    else require_once ('pages/404.php');
}
//если в url передано меньше двух параметров
elseif (count($params) < 2) {
    $routes = [
        '' => 'pages/main.php',
        'offers' => 'pages/offers.php',
        'about' => 'pages/about.php',
        'guarantees' => 'pages/guarantees.php',
    ];
    if (isset($routes[$request_url])) require_once $routes[$request_url];
    else require_once ('pages/404.php');
}

else require_once ('pages/404.php');
  • Вопрос задан
  • 1301 просмотр
Решения вопроса 1
nokimaro
@nokimaro
Меня невозможно остановить, если я смогу начать.
сократить .htaccess до такого

AddDefaultCharset UTF-8
RewriteEngine on
RewriteRule !index\.php$ index.php [L]


Две вычеркнутых строчки как раз означают то что если передан существующий файл или существующая папка, то не реврайтить на index.php
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d


Не вижу никаких проблем, с точки зрения безопасности, что существующие файлы отдаются напрямую, без реврайта. Просто не делайте чтобы в корне веб сервера лежали какие-либо скрипты кроме безопасных или index.php. Все остальные скрипты выносите выше корня веб-сервера (чтобы их в принципе нельзя было открыть через url)

Важный нюанс: если вы будете абсолютно все запросы реврайтить на index.php - то и все статичные файлы (css, jpg, js) которые раньше отдавались напрямую, будут перенаправлены на index.php и там вам придётся самому разруливать их отдачу, считывать содержимое файла, проставлять mime-type и тд.
Ответ написан
Пригласить эксперта
Ответы на вопрос 2
FanatPHP
@FanatPHP
Чебуратор тега РНР
Есть такая пословица, "дурная голова ногам покою не даёт".

я думаю, что это плохо с точки зрения безопасности.

С какого перепугу?

Если есть файлы, которые не надо светить наружу, их просто кладут за document root
А такой "роутинг" ничего кроме головной боли не даст.
Ответ написан
Комментировать
@AndryG
Добавлю для потомков. Единая точка входа может быть построена на более простом модуле, 99% уже используемом, - mod_dir

Часто желательно, чтобы один файл или ресурс обрабатывал все запросы к конкретному каталогу, кроме тех запросов, которые соответствуют существующему файлу или сценарию. Это часто называют «фронтальным контроллером».

В более ранних версиях HTTPD, этот эффект , как правило , требуется mod_rewrite, и использование из -fи -dтестов для файлов и каталогов существования. Теперь для этого требуется только одна строка конфигурации.

FallbackResource / index . PHP
Существующие файлы, такие как изображения, файлы CSS и т. Д., Будут обслуживаться в обычном режиме.

Используйте disabledаргумент, чтобы отключить эту функцию, если наследование от родительского каталога нежелательно.



Пример с работающего сайта:
...
    <Directory "$base/$proj/www/i">
      FallbackResource disabled  - в папке картинок отключаем обработчик
      Header set Cache-Control "public, max-age=31536000"
    </Directory>

    <Directory "$base/$proj/www">
        Options -Indexes
        Require all granted
        DirectoryIndex disabled
        DirectorySlash Off
        FallbackResource /entry.php
    </Directory>
</Macro>
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы