Por que o PDO é melhor para escapar de consultas/querystrings do MySQL do que mysql_real_escape_string?

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

Pergunta

Disseram-me que seria melhor usar PDO para escape do MySQL, em vez de mysql_real_escape_string.

Talvez eu esteja tendo um dia de morte cerebral (ou pode ser o fato de que não sou um programador natural, e ainda estou no estágio de novato quando se trata de PHP), mas ter verifiquei o manual do PHP e li a entrada em DOP, ainda não estou mais claro sobre o que PDO realmente é e por que é melhor do que usar mysql_real_escape_string.Isso pode ser porque eu ainda não entendi as complexidades da POO (presumo que tenha algo a ver com POO), mas além do fato de que variáveis ​​​​e valores de array parecem ter dois pontos na frente deles, Ainda não tenho certeza do que realmente é e como você o usa (e por que é melhor do que mysql_real_escape_string.(Também pode ter algo a ver com o fato de que eu realmente não tenho uma compreensão clara do que são 'classes', então quando leio "classe DOP" não percebo nada).

Tendo lido um artigo ou dois na parte 'Developer Zone' do site MySQL, ainda não estou mais claro.Como não consigo nem descobrir o que é no momento, acho que provavelmente usá-lo está um pouco além do meu alcance no momento, mas ainda estou interessado em ampliar minha formação e descobrir como posso melhorar as coisas.

Alguém poderia me explicar em 'inglês simples' o que é DOP (ou me indicar algo sobre o assunto escrito em inglês simples) e como você faria para usá-lo?

Foi útil?

Solução

Como as respostas atuais entram em detalhes, enquanto sua pergunta visa mais uma visão geral, tentarei:

As classes PDO visam encapsular todas as funcionalidades necessárias para interagir com um banco de dados.Eles fazem isso definindo 'métodos' (sala OO para funções) e 'propriedades' (sala OO para variáveis).Você os usaria como um substituição completa para todas as funções 'padrão' que você está usando agora para se comunicar com um banco de dados.

Então, em vez de chamar uma série de funções 'mysql_doSomething()', armazenando seus resultados em suas próprias variáveis, você 'instanciaria' um objeto da classe PDO ('class' = definição abstrata, 'objeto' = instância concreta e utilizável de uma classe) e chamar métodos nesse objeto para fazer o mesmo.

Por exemplo, sem DOP, você faria algo assim:

// 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;
}

embora isso seria o equivalente usando DOP:

// 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();

Portanto, à primeira vista, não há muita diferença, exceto na sintaxe.Mas a versão PDO tem algumas vantagens, sendo a maior delas a independência do banco de dados:

Se você precisar se comunicar com um banco de dados PostgreSQL, você apenas alterará mysql:para pgsql: na chamada de instanciação new PDO().Com o método antigo, você teria que passar por todo o seu código, substituindo todas as funções 'mysql_doSomething()' pelas suas contrapartes 'pg_doSomthing()' (sempre verificando possíveis diferenças no tratamento de parâmetros).O mesmo aconteceria com muitos outros mecanismos de banco de dados suportados.

Então, voltando à sua pergunta, o PDO basicamente oferece uma maneira diferente de conseguir as mesmas coisas, ao mesmo tempo que oferece alguns atalhos/melhorias/vantagens.Por exemplo, o escape aconteceria automaticamente da maneira adequada e necessária para o mecanismo de banco de dados que você está usando.Além disso, a substituição de parâmetros (evita injeções de SQL, não mostradas no exemplo) é muito mais fácil, tornando-a menos propensa a erros.

Você deveria ler alguns princípios básicos de OOP para ter uma ideia de outras vantagens.

Outras dicas

Não estou muito familiarizado com o PDO, mas há uma distinção entre "declarações preparadas" e strings de escape.Fugir é sobre removendo cadeias de caracteres não permitidas da consulta, mas as declarações preparadas são sobre informando ao banco de dados que tipo de consulta esperar.

Uma consulta tem várias partes

Pense desta forma:quando você faz uma consulta ao banco de dados, você está informando várias coisas separadas.Uma coisa pode ser, por exemplo, "quero que você faça uma seleção". Outro pode ser "limitá -lo a linhas onde o nome do usuário é o seguinte valor".

Se você criar uma consulta como uma string e entregá-la ao banco de dados, ele não conhecerá nenhuma das partes até obter a string completa.Você pode fazer isso:

'SELECT * FROM transactions WHERE username=$username'

Quando obtém essa string, ele precisa analisá-la e decidir "este é um SELECT com um WHERE".

Misturando as peças

Suponha que um usuário mal-intencionado insira seu nome de usuário como billysmith OR 1=1.Se você não tomar cuidado, você pode colocar isso em sua string, resultando em:

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

...que retornaria todas as transações para todos os usuários, porque 1 sempre é igual a 1.Opa, você foi hackeado!

Veja o que aconteceu? O banco de dados não sabia quais partes esperar da sua consulta, então apenas analisou a string.Não foi surpresa que o WHERE tinha um OR, com duas condições que poderiam satisfazê-lo.

Mantendo as peças retas

Se ao menos soubesse o que esperar, ou seja, um SELECT cujo WHERE tivesse apenas uma condição, o usuário mal-intencionado não poderia tê-lo enganado.

Com uma declaração preparada, você pode dar a expectativa correta.Você pode dizer ao banco de dados "Estou prestes a lhe enviar um SELECT, e será limitado a linhas WHERE username = uma corda que estou prestes a lhe dar.Isso é tudo - não há outras partes na consulta.Você está pronto?OK, aqui vem a string para comparar com o nome de usuário."

Com essa expectativa, o banco de dados não seria enganado:ele retornaria apenas linhas onde o username A coluna contém a sequência real 'Billysmith ou 1 = 1.' Se ninguém tiver esse nome de usuário, ele não retornaria nada.

Outros benefícios das declarações preparadas

Além dos benefícios de segurança, as declarações preparadas apresentam alguns benefícios de velocidade:

  • Eles podem ser reutilizados com parâmetros diferentes, o que deve ser mais rápido do que construir uma nova consulta do zero, porque o banco de dados já sabe basicamente o que você está prestes a solicitar.Já construiu seu "plano de consulta".
  • Alguns bancos de dados (Postgres é um, eu acho) começarão a fazer um plano de consulta assim que receberem a instrução preparada - antes de você realmente enviar os parâmetros para usar com ele.Portanto, você poderá ver uma aceleração mesmo na primeira consulta.

Para outra explicação, veja a resposta de Theo aqui.

Ao contrário de mysql_real_escape_string, o PDO permite impor um tipo de dados.

<?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();
?>

Observe que no exemplo acima, o primeiro parâmetro, calorias, deve ser um número inteiro (PDO::PARAM_INT).

Em segundo lugar, para mim, as consultas parametrizadas do PDO são mais fáceis de ler.Prefiro ler:

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

que

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

Terceiro, você não precisa citar os parâmetros corretamente.O DOP cuida disso.Por exemplo, mysql_real_query_string:

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

contra

SELECT * FROM user WHERE name = ?

Finalmente, o PDO permite portar seu aplicativo para um banco de dados diferente sem alterar suas chamadas de dados PHP.

imagine que você escreve algo como:

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

isso não irá salvá-lo de injeções, porque $id pode ser 1 OR 1=1 e você obterá todos os registros da tabela.você teria que converter $id para o tipo de dados correto (int nesse caso)

O pdo tem outra vantagem: a intercambialidade dos back-ends do banco de dados.

Além de evitar injeção de SQL, o PDO permite preparar uma consulta uma vez e executá-la diversas vezes.Se sua consulta for executada múltiplas vezes (dentro de um loop, por exemplo), este método deverá ser mais eficiente (eu digo "deveria ser", porque parece que nem sempre é o caso em versões mais antigas do MySQL).O método prepare/bind também está mais alinhado com outras linguagens com as quais trabalhei.

Por que o PDO é melhor para escapar de consultas/querystrings do MySQL do que mysql_real_escape_string?

Simplesmente porque “escapar” por si só não faz sentido.
Além disso, é diferente incomparável assuntos.

O único problema de escapar é que todo mundo entende errado, assumindo isso como uma espécie de "proteção".
Todo mundo diz "Escapei das minhas variáveis" com o significado "Protegi minha consulta".
Enquanto escapar sozinho não tem nada a ver com proteção.

A proteção pode ser alcançada aproximadamente em caso de Eu escapei e citei meus dados, mas não é aplicável em todos os lugares, para os identificadores, por exemplo (assim como para o PDO, aliás).

Então, a resposta é:

  • O DOP, ao escapar para os valores vinculados, aplica não apenas o escape, mas também a citação - por isso é melhor.
  • “escapar” não é sinônimo de “proteção”."escapar + citar" aproximadamente é.
  • mas para algumas partes da consulta ambos os métodos são inaplicáveis.
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top