klein - php site routing
Mod-Rewrite o enrutador PHP? (2)
Estoy debatiendo enrutar mis solicitudes con una de las dos opciones:
Opción 1: ruta de captura simple con Mod-Rewrite y embudo escrito $_GET
ruta a index.php para cargar ...
#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]
Opción 2: simplemente enrute las solicitudes al controlador frontal y cree una clase de enrutamiento PHP para manejar el enrutamiento ...
#default routing
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?rt=$1 [L,QSA]
/* --- on front controller, process $_GET[''rt''] --- */
al final del día, ¿qué será más rápido, más fácil de asegurar y más fácil de mantener?
cualquier otra idea?
NOTA: No estoy ejecutando un marco conocido. Estoy construyendo mi propio patrón MVC para aprenderlo.
Por lo general, en marcos MVC, este tipo de cosas generalmente se maneja mejor con un controlador frontal (llamado index.php
o similar). Usas mod_rewrite para esconder index.php
de todas las URL para que tus usuarios vean buenas rutas limpias.
También es mucho más fácil de manejar en PHP que en las directivas de reescritura de Apache. PHP es mucho más flexible y fácil de escribir / comprender. No estoy seguro de haber visto mod_rewrite como el único motor de enrutamiento para cualquier estructura web, ahora que lo pienso.
Su segundo fragmento de código es el camino a seguir para sus directivas de reescritura.
Yo también estoy en el proceso de construir un sistema LAMP MVC desde cero.
Pregunta de la clase MVC Router
Actuación
Después de haber creado una secuencia de comandos bash shell para compilar Apache 2.4.x desde la fuente, observa que una biblioteca de Expresión regular compatible con Perl está incorporada en el proceso. Cada vez que se use el código de expresión regular, la respuesta del servidor http será más lenta. Por lo tanto, la opción número uno es no ir si el rendimiento es su preocupación. Hay un costo para los análisis involucrados con las expresiones regulares. El servidor web Apache toma prestada la lógica para expresiones regulares. No es el código local de Apaches.
Seguridad
La seguridad es un problema diferente. En primer lugar, nada acerca de reescribir las URL las hace seguras. Es simple seguridad a través de la oscuridad y hacer que las cosas se vean bonitas en el lado del cliente. De vez en cuando, los agujeros de seguridad se encuentran en el código del motor de expresión regular. Por lo tanto, en términos de seguridad real, se queda en la misma posición básica en la que estaría sin ninguna reescritura: las personas o los bots pueden enviar cosas malas a su servidor y necesita una forma de filtrar y validar los datos de manera sistemática. Asegúrese de filtrar y validar todas las entradas, especialmente cualquier parte de la cadena de consulta reescrita que desee utilizar.
Por lo tanto, la opción número uno presenta una interfaz más limpia ( INPUT_GET
/ $_GET
) para iniciar sus tareas de seguridad. La opción número dos requiere (si está tratando de ser minucioso) que filtre y valide toda la cadena como primer paso. El segundo paso (en general) será dividir y extraer lo que esperas reunir de la cadena más grande.
Una vez más, debe filtrar y validar cada parte de la cadena. Por lo tanto, si bien es más manejable (más fácil, conveniente) filtrar / validar / desglosar / extraer / la cadena más grande en PHP (digamos, con un método en clase de seguridad de algún tipo), aún necesita hacer el trabajo para cada pieza para cada solicitud La opción número uno le ahorra la molestia de tener que dividir la cadena más grande por el costo de ejecutar el motor de expresiones regulares en cada solicitud. Pero, en su mayor parte, puede comenzar a filtrar y validar los elementos que espera recibir en INPUT_GET
o $_GET
.
Sin embargo, tenga en cuenta que la opción uno es principalmente para personas que realmente entienden cómo funcionan las expresiones regulares y cómo esto se aplica a las posibles URL que su servidor puede recibir. Si necesita más de una RewriteRule
, podría ser para que pueda tener algo como esto (u otras razones) entrar en el servidor.
index.php?0=model
index.php?0=model&1=method
index.php?0=model&1=method&2=methodArgs
Esto hace que sea más fácil filtrar y validar sus entradas. Sin embargo, tenga en cuenta que la última línea implica que aún puede necesitar dividir líneas y filtrar / validar más (pero puede que no tenga que suceder en cada solicitud, como ocurre en la opción número 1).
Ejemplo de código : obtención de parámetros de URL con la opción 2 (¡comience en la parte inferior!)
Nota : Estas son solo algunas cosas a considerar, no "la" manera de hacerlo.
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.
}
Resumen
Si la seguridad es su principal preocupación (es decir, su interfaz en su esquema de seguridad), tome la decisión y use la opción número uno. Aprender mod_rewrite y reescritura de URL te hace bastante poderoso. ¿Por qué dejar ese poder sobre la mesa? Apache es un animal extraño a la hora de configurarlo. Pero, si comprende las URL y las expresiones regulares, le digo hombre / mujer y voy por ello. :-) Si la velocidad, la comprensión y la facilidad de uso son sus principales preocupaciones, vaya por la opción número uno. Hay fanáticos que quieren que todo esté codificado en PHP, pero debes juzgar por ti mismo cuáles son los pros y los contras de ambas situaciones.
Actualización : Mi mal. Este código funcionaría mejor para la opción número 1. En la opción número 2, 1 = bla, donde blah sería algo como /trt/43ff/3335/f/3/fr3r/
o lo que sea. No tendrás que buscar ampersands.
PHP: filter_inpur_array (), (use INPUT_GET)