Я обсуждаю маршрутизацию своих запросов одним из двух вариантов:
Вариант 1: простой маршрут захвата с Mod-Rewrite и воронкой, написанной маршрутом $_GET
в index.php для загрузки …
#default routing RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^blog/([0-9]+)?$ index.php?rt=blog¶ms=$1 [L,QSA] // ..more custom routes, and then a default route RewriteRule ^([A-Za-z]+)/([A-Za-z]+)/(.*)?$ index.php?rt=$1/$2¶ms=$3 [L,QSA]
Вариант 2: просто направьте запросы на Front Controller и создайте класс маршрутизации PHP для обработки маршрутизации …
#default routing RewriteCond %{REQUEST_FILENAME} !-f RewriteCond %{REQUEST_FILENAME} !-d RewriteRule ^(.*)$ index.php?rt=$1 [L,QSA] /* --- on front controller, process $_GET['rt'] --- */
в конце дня, который будет работать быстрее, проще в безопасности и будет проще поддерживать?
любые другие идеи?
ПРИМЕЧАНИЕ. Я не использую известную структуру. Я создаю свой собственный шаблон MVC, чтобы узнать его.
Обычно в структурах MVC такие вещи обычно лучше всего обрабатывают передним контроллером (с именем index.php
и т. П.). Вы используете mod_rewrite, чтобы скрыть index.php
со всех URL-адресов, чтобы ваши пользователи видели хорошие чистые пути.
Это также проще в PHP, чем в директивах переписывания Apache. PHP намного гибче и проще писать / понимать. Я не уверен, что когда-либо видел, что mod_rewrite используется как единственный механизм маршрутизации для любой веб-структуры, теперь, когда я думаю об этом.
Второй фрагмент кода – это путь для ваших директив переписывания.
Я тоже занимаюсь созданием системы LAMP MVC с нуля.
Вопрос класса маршрутизатора MVC
Представление
Создав сценарий оболочки bash для компиляции Apache 2.4.x из исходного кода, вы заметите, что в процесс выпекается библиотека регулярного выражения Perl Compatible Regular Expression. В любое время, когда должен использоваться код регулярного выражения, ответ HTTP-сервера будет медленнее. Следовательно, вариант номер один – это не гонка, если вы беспокоитесь о производительности. Стоимость аналитики связана с регулярными выражениями. Веб-сервер Apache заимствует логику регулярных выражений. Это не домашний код Апачей.
Безопасность
Безопасность – это другая проблема. Во-первых, ничего о переписывании URL-адресов не делает их безопасными. Это простая защита через неясность и делает вещи выглядят красиво на стороне клиента. Время от времени дыры в безопасности обнаруживаются в коде двигателя регулярных выражений. Таким образом, с точки зрения истинной безопасности вы остаетесь в том же базовом положении, в котором вы были бы без перезаписи: люди или боты могут отправлять плохие вещи на ваш сервер, и вам нужен способ фильтровать и проверять ввод системным образом. Обязательно фильтруйте и проверяйте все входные данные, особенно любую часть переписанной строки запроса, которую вы собираетесь использовать.
Таким образом, вариант номер один представляет более чистый интерфейс ( INPUT_GET
/ $_GET
) для исполнения ваших обязанностей по обеспечению безопасности. Параметр номер два требует (если вы пытаетесь быть тщательным), вы должны фильтровать и проверять всю строку в качестве первого шага. Второй шаг (в общем случае) – разбить и извлечь то, что вы надеетесь собрать из большей строки.
Опять же, вы должны фильтровать и проверять каждую часть строки. Следовательно, хотя, возможно, более легко (проще и удобнее) фильтровать / проверять / разбивать / извлекать / большую строку в PHP (скажем, с помощью метода в классе безопасности), вам все равно нужно выполнять работу для каждой части , для каждого запроса. Вариант номер один избавляет вас от необходимости разбивать большую строку на затраты на выполнение механизма регулярных выражений по каждому запросу. Но, по большей части, вы можете просто начать фильтрацию и проверку элементов, которые вы ожидаете получить в INPUT_GET
или $_GET
.
Обратите внимание, что этот вариант в основном предназначен для людей, которые действительно понимают, как работают регулярные выражения, и как это относится к потенциальным URL-адресам, которые может получить ваш сервер. Если вам нужно больше одного RewriteRule
, это может быть так, что вы можете иметь что-то подобное (или другие причины) на сервере.
index.php?0=model index.php?0=model&1=method index.php?0=model&1=method&2=methodArgs
Это облегчает фильтрацию и проверку ваших входов. Обратите внимание, однако, что последняя строка подразумевает, что вам все равно необходимо выполнить разделение строк и дальнейшую фильтрацию / проверку (но это может не произойти при каждом запросе, как это делает в варианте номер 1).
Пример кода : получение параметров URL с помощью опции 2 (начало внизу!)
Примечание . Это всего лишь некоторые вещи, которые нужно учитывать, а не «способ» сделать это.
const QS_ARRAY_LIMIT = 3; private function getPairValue($delimiter, $string) { return explode('$delimiter', $string)[1]; //Get the value for a pair. } private function isMultiValuedQueryString() { return (mb_strpos($this->queryStr, '&', 0, 'UTF-8') > 2); } private function getAllowedPairs($argsStr) { $pairs = explode('&', $argsStr); $numPairs = count($pairs); if($numPairs > self::QS_ARRAY_LIMIT) { throw new SecurityException("Too many query string pairs ({$numPairs}) submitted to the router.\n"); } return $pairs; } private function isQueryStrPair($pair) { $equalPos = null; $pairLength = mb_strlen($pair, 'UTF-8'); if($pairLength < 3) { throw new SecurityException("Query string pair is too short: Length: {$pairLength}!, Suspect: {$pair}\n"); //Sends to '/' } $equalPos = mb_strpos($pair, '=', 0, 'UTF-8'); if($equalPos === 0) //The first position. { throw new SecurityException("Query sting pair cannot *start* with an equal sign (=): Suspect: {$pair}\n"); //Sends to '/' } if($equalPos === ($pairLength - 1)) //The last position. { throw new SecurityException("Query sting pair cannot *end* with an equal sign (=): Suspect: {$pair}\n"); //Sends to '/' } return true; } private function getQueryStringArgs($url) { $delimiter = '?'; if(mb_strpos($url, $delimiter, 0, 'UTF-8') > 0) { return $this->getPairValue($delimiter, $url); } throw new RuntimeException("Malformed URL passed to query string parser."); } private function associateArgPairs(array $argPairs, array $values) { $i = 0; foreach($argPairs as $key => &value) { if(isset($values[$i])) { $value[$key] = $values[$i]; ++$i; } } return $argPairs; } private function getQueryStrValues($url) { $delimiter = '='; $argPairs = ['model' => null, 'method' => null, 'methodArgs' => null] $inputValues = []; // ================================================= // Valid query strings might look like (amongst many combinations): // // index.php?arg1=foo&agr2=bar&arg3=/baz/bang/boom // // Or, just one pair with no ampersand,'&'. // // index.php?arg1=foo // ================================================== // Get everything after the question mark, '?'. $queryStringArgsStr = $this->getQueryStringArgs($url); if($this->isMultiValuedQueryString($queryStringArgsStr)) //Check if '&' exists. { foreach($this->getAllowedPairs($queryStringArgsStr) as $pair) { if($this->isQueryStrPair($pair)) { //Get the value for each pair., using '=' as the string delimiter. $inputValues[] = $this->getPairValue($delimiter, $pair); } } } else { if($this->isQueryStrPair($queryStringArgsStr)) { $inputValues[] = $this->getPairValue($delimiter, $queryStringArgsStr); //Get the value for each pair. } } return $this->associateArgPairs($argPairs, $inputValues); //Remember, you will still need to split up $argPairs[$methodArgs] if necessary. //With option #1, you could start closer to this point, //and hence filter and validate sooner. }
Резюме
Если безопасность является вашей основной задачей (то есть ваш интерфейс в вашей схеме безопасности), укусите пулю и используйте вариант номер один. Изучение mod_rewrite и перезаписи URL-адресов делает вас довольно мощным. Зачем оставлять эту власть на столе? Apache – странное животное, когда дело доходит до его настройки. Но, если вы понимаете URL-адреса и регулярные выражения, я говорю «мужчина / женщина» и продолжаю это. 🙂 Если ваша задача связана с быстротой, пониманием и простотой использования, перейдите на вариант номер один. Есть фанатики, которые хотят, чтобы все было закодировано на PHP, но вы должны сами судить о том, что за плюсы и минусы в обеих ситуациях.
Обновление : плохо. Этот код действительно будет работать лучше для опции номер 1. В опции номер 2, 1 = blah, где blah будет что-то вроде /trt/43ff/3335/f/3/fr3r/
или что угодно. Вам не придется искать амперсандов.
PHP: filter_inpur_array (), (используйте INPUT_GET)
PHP: Суперглобалы
PHP: explode ()
PHP: foreach (array_expression as $ key => $ value)
PHP: многобайтовые строковые функции