Anch'io sono in procinto di creare un sistema LAMP MVC da zero.
MVC Router Class Question
prestazioni
Dopo aver creato uno script di shell bash per compilare Apache 2.4.x dai sorgenti, si nota che una libreria per espressioni regolari compatibili Perl viene cotto nel processo. Ogni volta che deve essere usato il codice dell'espressione regolare, la risposta del server http sarà più lenta. Quindi, l'opzione numero uno è un no go se la prestazione è la tua preoccupazione. C'è un costo per l'analisi coinvolta con le espressioni regolari. Il server Web Apache prende in prestito la logica per le espressioni regolari. Non è un codice di casa sviluppato da Apaches.
Security
La sicurezza è una questione diversa. Innanzitutto, nulla sulla riscrittura degli URL li rende sicuri. È semplice sicurezza attraverso l'oscurità e fare apparire le cose belle dal lato del cliente. Di tanto in tanto, i buchi di sicurezza si trovano nel codice del motore di espressioni regolari. Quindi, in termini di sicurezza reale, ti ritroverai nella stessa posizione di base in cui ti troverei senza alcuna riscrittura: le persone oi robot possono inviare cose cattive al tuo server e hai bisogno di un modo per filtrare e convalidare l'input in modo sistematico. Assicurati di filtrare e convalidare tutti gli input, specialmente ogni parte della stringa di query riscritta che intendi utilizzare.
Pertanto, l'opzione numero uno presenta un'interfaccia più pulita (INPUT_GET
/$_GET
) per l'avvio delle attività di sicurezza. L'opzione numero due richiede (se si sta cercando di essere approfonditi) di filtrare e convalidare l'intera stringa come primo passo. Il secondo passo (in generale) sarà quello di separare ed estrarre ciò che speri di raccogliere dalla stringa più grande.
Anche in questo caso, è necessario filtrare e convalidare ogni parte della stringa. Quindi, mentre forse è più gestibile (più facile, conveniente) filtrare/convalidare/spezzare/estrarre/la stringa più grande in PHP (diciamo, con un metodo in una classe di sicurezza di qualche tipo), devi comunque lavorare per ogni pezzo , per ogni richiesta L'opzione numero uno evita di dover spezzare la stringa più grande per il costo dell'esecuzione del motore regex a ogni richiesta. Ma, per la maggior parte, puoi iniziare a filtrare e convalidare gli elementi che ti aspetti di ricevere in INPUT_GET
o $_GET
.
Si noti, tuttavia, che l'opzione 1 è principalmente per le persone che capiscono veramente come funzionano le espressioni regolari e come questo si applica ai potenziali URL che il server può ricevere. Se hai bisogno di più di uno RewriteRule
, è possibile che tu possa avere qualcosa del genere (o altri motivi) entrare nel server.
index.php?0=model
index.php?0=model&1=method
index.php?0=model&1=method&2=methodArgs
In questo modo è più facile filtrare e convalidare gli input. Si noti, tuttavia, che l'ultima riga implica che è ancora necessario eseguire alcune suddivisioni in linea e ulteriori filtri/convalida (ma ciò potrebbe non essere necessario per ogni richiesta, come nel caso dell'opzione numero 1).
codice di esempio: Ottenere parametri URL utilizzando l'opzione 2 (Start in basso!)
Nota: Queste sono solo alcune cose da considerare, non "il" modo per farlo.
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.
}
Sommario
Se la sicurezza è la preoccupazione principale (vale a dire, l'interfaccia nel vostro sistema di sicurezza), stringere i denti e utilizzare l'opzione numero uno. Apprendimento mod_rewrite e riscrittura degli URL ti rende piuttosto potente. Perché lasciare quel potere sul tavolo? Apache è uno strano animale quando si tratta di configurarlo. Ma, se capisci gli URL e le espressioni regolari, io dico uomo/donna e me ne vado. :-) Se la velocità, la comprensione e la facilità d'uso sono le tue preoccupazioni principali, scegli l'opzione numero uno. Ci sono fanatici che vogliono che tutto sia codificato in PHP, ma devi giudicare da solo quali sono i pro ei contro di entrambe le situazioni.
Aggiornamento: Il mio male. Questo codice funzionerebbe in realtà meglio per l'opzione numero 1. Nell'opzione numero 2, 1 = blah, dove blah sarebbe qualcosa come /trt/43ff/3335/f/3/fr3r/
o qualsiasi altra cosa. Non dovrai cercare e commerciali.
PHP: filter_inpur_array(), (use INPUT_GET)
PHP: Superglobals
PHP: explode()
PHP: foreach (array_expression as $key => $value)
PHP: Multibtye String Functions
che cosa si intende per sicuro? –
beh, ho appena pensato che ci siano misure da prendere per essere sicuro che il mio sistema/framework/etc non abbia aperture che non conosco. solo supponendo di essere più ingenuo di quanto mi auguro – johnnietheblack
Apprezzo i tuoi sforzi. –