Perché PDO è migliore per sfuggire alle query/querystring MySQL rispetto a mysql_real_escape_string?

StackOverflow https://stackoverflow.com/questions/1742066

Domanda

Mi è stato detto che sarebbe stato meglio usarlo PDO per l'escape di MySQL, piuttosto che mysql_real_escape_string.

Forse sto passando una giornata cerebralmente morta (o potrebbe essere il fatto che non sono affatto un programmatore naturale e sono ancora allo stadio di un principiante quando si tratta di PHP), ma avendo controlla il manuale PHP e leggi la voce DOP, non mi è ancora chiaro cosa sia effettivamente PDO e perché sia ​​meglio dell'uso mysql_real_escape_string.Ciò potrebbe essere dovuto al fatto che non sono ancora riuscito a comprendere le complessità dell'OOP (suppongo che abbia qualcosa a che fare con l'OOP), ma a parte il fatto che le variabili e i valori dell'array sembrano avere due punti davanti a loro, Non sono ancora sicuro di cosa sia realmente e di come lo usi (e perché sia ​​meglio di mysql_real_escape_string.(Potrebbe anche avere qualcosa a che fare con il fatto che non ho una chiara comprensione di cosa siano le "classi", quindi quando leggo "classe PDO" non ne sono affatto più saggio).

Avendo letto un articolo o due nella parte "Developer Zone" del sito Web MySQL, non sono ancora più chiaro.Dato che non riesco nemmeno a capire di cosa si tratta al momento, penso che probabilmente usarlo sia un po' al di là delle mie capacità in questo momento, ma sono ancora interessato ad ampliare la mia formazione e scoprire come potrei migliorare le cose.

Qualcuno potrebbe spiegarmi in "inglese semplice" cos'è PDO (o indicarmi qualcosa sull'argomento scritto in inglese semplice) e come lo utilizzeresti?

È stato utile?

Soluzione

Poiché le risposte attuali entrano nei dettagli mentre la tua domanda è più mirata a una panoramica generale, ci proverò:

Le classi PDO mirano a incapsulare tutte le funzionalità necessarie per interagire con un database.Lo fanno definendo "metodi" (salotto OO per funzioni) e "proprietà" (salotto OO per variabili).Li useresti come a sostituzione completa per tutte le funzioni "standard" che stai utilizzando ora per comunicare con un database.

Quindi, invece di chiamare una serie di funzioni 'mysql_doSomething()', memorizzando i loro risultati nelle tue variabili, dovresti 'istanziare' un oggetto dalla classe PDO ('class' = definizione astratta, 'oggetto' = istanza concreta e utilizzabile di una classe) e chiamare metodi su quell'oggetto per fare lo stesso.

Ad esempio, senza PDO, faresti qualcosa del genere:

// Get a db connection
$connection = mysql_connect('someHost/someDB', 'userName', 'password');
// Prepare a query
$query = "SELECT * FROM someTable WHERE something = " . mysql_real_escape_string($comparison) . "'";
// Issue a query
$db_result = mysql_query($query);
// Fetch the results
$results = array();
while ($row = mysql_fetch_array($db_result)) {
  $results[] = $row;
}

mentre questo sarebbe l'equivalente utilizzando PDO:

// Instantiate new PDO object (will create connection on the fly)
$db = new PDO('mysql:dbname=someDB;host=someHost');
// Prepare a query (will escape on the fly)
$statement = $db->prepare('SELECT * FROM someTable WHERE something = :comparison');
// $statement is now a PDOStatement object, with its own methods to use it, e.g.
// execute the query, passing in the parameters to replace
$statement->execute(array(':comparison' => $comparison));
// fetch results as array
$results = $statement->fetchAll();

Quindi a prima vista non c'è molta differenza, tranne che nella sintassi.Ma la versione PDO presenta alcuni vantaggi, il più grande dei quali è l'indipendenza dal database:

Se invece avessi bisogno di parlare con un database PostgreSQL, cambieresti solo mysql:A pgsql: nella chiamata di istanziazione new PDO().Con il vecchio metodo, dovresti esaminare tutto il codice, sostituendo tutte le funzioni 'mysql_doSomething()' con la loro controparte 'pg_doSomthing()' (controllando sempre eventuali differenze nella gestione dei parametri).Lo stesso varrebbe per molti altri motori di database supportati.

Quindi, per tornare alla tua domanda, PDO fondamentalmente ti offre semplicemente un modo diverso per ottenere le stesse cose, offrendo allo stesso tempo alcune scorciatoie/miglioramenti/vantaggi.Ad esempio, l'escape avverrebbe automaticamente nel modo corretto necessario per il motore di database che stai utilizzando.Anche la sostituzione dei parametri (previene le SQL Injection, non mostrate nell'esempio) è molto più semplice, rendendola meno soggetta a errori.

Dovresti documentarti alcune nozioni di base sull'OOP per avere un'idea di altri vantaggi.

Altri suggerimenti

Io non sono super familiarità con DOP, ma c'è una distinzione tra "dichiarazioni preparate" e sfuggito stringhe. Fuggire è di circa rimozione di stringhe di caratteri non consentiti dalla query, ma le istruzioni preparate sono circa dicendo la banca dati che tipo di query per aspettarsi .

Una query dispone di più parti

Pensare in questo modo: quando si dà una query al database, stai dicendo che molte cose separate. Una cosa che potrebbe essere, per esempio, "Voglio che tu faccia una select". Un altro potrebbe essere "limitare il sistema ai righe in cui il nome utente è il seguente valore".

Se si crea una query come una stringa e consegnarlo alla base di dati, che non conosce o parte fino a quando non ottiene la stringa completata. Si potrebbe fare questo:

'SELECT * FROM transactions WHERE username=$username'

Quando si arriva quella stringa, deve analizzare e decidere "questo è un SELECT con un WHERE".

Per le parti mescolate

Supponiamo che un utente malintenzionato immette il nome utente come billysmith OR 1=1. Se non stai attento, si potrebbe mettere che nella vostra stringa, con conseguente:

'SELECT * FROM transactions WHERE username=billysmith OR 1=1'

... che sarebbe tornato tutte le transazioni per tutti gli utenti , perché 1 è sempre uguale 1. Ops, hai hackerato!

Vedere che cosa è successo? Il database non sapeva cosa aspettarsi parti nella query , in modo che solo analizzato la stringa. Non è stato sorpreso dal fatto che il WHERE ha avuto un OR, con due condizioni che potrebbero soddisfarla.

Mantenere le parti direttamente

Se solo avesse saputo cosa aspettarsi , vale a dire, un SELECT cui WHERE aveva una sola condizione, l'utente malintenzionato potrebbe non hanno ingannato esso.

Con una dichiarazione preparata, si può dare quella giusta aspettativa. . Si si può dire al database "Sto per inviare un SELECT, e sta andando ad essere limitato alle righe WHERE username = una stringa che sto per darvi Questo è tutto - non ci sono altre parti alla query Are. Sei pronto? OK, ecco che arriva la stringa da confrontare con il nome utente ".

Con questa aspettativa, il database non sarebbe ingannare: sarebbe restituire solo le righe in cui la colonna username contiene l'effettiva stringa 'billysmith OR 1 = 1.' Se nessuno ha quel nome utente, sarebbe tornare nulla.

Altri vantaggi di istruzioni preparate

Oltre alle prestazioni di sicurezza, istruzioni preparate hanno un paio di vantaggi di velocità:

  • Possono essere riutilizzati con parametri diversi, che dovrebbe essere più veloce di costruire una nuova query da zero, perché il database sa già fondamentalmente ciò che si sta per chiedere. Essa ha già costruito il suo "piano di query".
  • Alcuni database (Postgres è uno, credo) potranno iniziare a fare un piano di query non appena ottengono la dichiarazione preparata - prima di aver effettivamente inviato i parametri da utilizzare con esso. Così si può vedere un aumento di velocità anche sulla prima query.

Per un'altra spiegazione, vedere di Theo risposta qui .

A differenza di mysql_real_escape_string, PDO permette di imporre un tipo di dati.

<?php
/* Execute a prepared statement by binding PHP variables */
$calories = 150;
$colour = 'red';
$sth = $dbh->prepare('SELECT name, colour, calories
    FROM fruit
    WHERE calories < :calories AND colour = :colour');
$sth->bindParam(':calories', $calories, PDO::PARAM_INT);
$sth->bindParam(':colour', $colour, PDO::PARAM_STR, 12);
$sth->execute();
?>

Si noti che nell'esempio di cui sopra, il primo parametro, calorie, è necessario per essere un numero intero (DOP :: PARAM_INT).

In secondo luogo, per me, DOP parametrizzata query sono più facili da leggere. Preferisco leggere:

SELECT name FROM user WHERE id = ? AND admin = ? 

di

SELECT name FROM user WHERE id = mysql_real_escape_string($id) AND admin = mysql_real_escape_string($admin);

In terzo luogo, non c'è bisogno per essere sicuri di citare i parametri in modo corretto. DOP si occupa di questo. Ad esempio, mysql_real_query_string:

SELECT * FROM user WHERE name = 'mysql_real_escape_string($name)' //note quotes around param

vs

SELECT * FROM user WHERE name = ?

Infine, PDO permette alla porta la vostra applicazione ad un db diversa senza cambiare chiamate dati PHP.

immaginate di scrivere qualcosa sulla falsariga di:

$query = 'SELECT * FROM table WHERE id = ' . mysql_real_escape_string($id);

questo non vi salverà dalle iniezioni, perché $ id potrebbe essere 1 OR 1=1 e si otterrà tutti i record della tabella. che avrebbe dovuto lanciare $ id per il tipo di dati a destra (int in quel caso)

DOP ha un altro vantaggio, e che è l'intercambiabilità di backend di database.

Oltre a prevenire SQL injection, PDO permette di preparare una query una volta ed eseguirla più volte. Se la query viene eseguita più volte (all'interno di un ciclo, per esempio), questo metodo dovrebbe essere più efficiente (dico "dovrebbe essere", perché sembra che non è sempre il caso su versioni precedenti di MySQL). Il metodo di preparazione / bind è anche più in linea con le altre lingue con cui ho lavorato.

  

Perché è PDO meglio per sfuggire MySQL query / querystrings di mysql_real_escape_string?

Semplicemente perché "fuga" da solo non ha alcun senso.
Inoltre, è diverso incomparabili le cose.

L'unico problema con la fuga è che tutti la prende male, ammesso che come una sorta di "protezione".
Tutti dicono "Sono scappato mio variabili" con il significato "Ho protetto la mia ricerca".
Mentre in fuga da solo non ha nulla a che fare con la protezione a tutti.

La protezione può essere raggiunto più o meno in caso di sono scappata e ha citato i miei dati , ma non è applicabile in tutto il mondo, per gli identificatori, ad esempio (così come DOP, tra l'altro).

Quindi, la risposta è:

  • DOP, quando si fa sfuggire per i valori binded, si applica non solo fuggire, ma anche citando -. È per questo che è meglio
  • "fuga" non è sinonimo di "protezione". "Fuga + citando" grosso modo a dire.
  • ma per alcune parti di query entrambi i metodi inapplicabile.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top