Neden PDO mysql_real_escape_string daha MySQL sorgular / querystrings kaçmak için daha iyi?

6 Cevap php

Ben daha iyi PDO MySQL kaçan kullanarak, yerine mysql_real_escape_string olurdu söylendi.

Belki bir beyin ölü günü yaşıyorum (ya da ben hayal doğal bir programcı hiçbir streç değilim, ve PHP geldiğinde ben acemi aşamada çok hâlâ gerçek olabilir) sahip olan, ancak PHP manuel kontrol ve the entry on PDO, ben PDO aslında ne olduğu hala net değilim ve neden mysql_real_escape_string kullanarak daha iyi okuyun. Gerçekten henüz OOP karmaşıklığı ile kulpları yok ettik, çünkü bu, (ben OOP ile ilgili bir şey olduğunu kabul ediyorum), ama değişkenler ve dizi değerler bunlardan bir kolon Infront var gibi aslında başka olabilir Gerçekten net bir anlayış yok ki ben hala aslında ne olduğunu emin değilim ve bunu kullanmak (ve neden daha mysql_real_escape_string. daha iyi nasıl (Aynı zamanda gerçeği ile ilgili bir şey olabilir ne 'sınıflar', bu yüzden ben "PDO sınıfını" okuduğumda hiç akıllıca gerçekten) değilim.

an article veya MySQL web geliştirici Dilimi 'biraz üzerinde iki okumak zorunda, ben hala net değilim. Ben bile şu anda ne olduğunu anlamaya olamaz gibi, muhtemelen şu anda bana ötesinde biraz kullanarak düşünmek, ama ben hala benim eğitim genişletilmesi ve bir şeyleri geliştirmek nasıl bulma ilgileniyorum.

Herkes PDO ne 'düz İngilizce' bana açıklayabilir (veya düz İngilizce yazılmış konuyla ilgili bir şey yönde bana gelin), ve bunu nasıl kullanma hakkında gitmek istiyorum misiniz?

6 Cevap

Soru daha genel bir bakış hedefleniyor iken geçerli cevaplar ayrıntısına girmeyeceğim, ben bunu bir deneyeyim:

PDO sınıflar bir veritabanı ile etkileşim için gerekli tüm işlevselliği saklanması hedefliyoruz. Onlar 'yöntemleri' (fonksiyonlar için OO salon) ve 'özellikleri' (değişkenler için OO salon) tanımlayarak bunu. Eğer bir veritabanına konuşmak için şimdi kullanan tüm 'standart' fonksiyonları için complete replacement olarak kullanmak istiyorum.

Peki yerine kendi değişkenleri kendi sonuçlarını depolamak bir dizi 'mysql_doSomething ()' fonksiyonları, çağıran, sen 'instantiate' PDO sınıftan bir nesne = soyut bir tanım ('sınıf', 'nesne' = beton, kullanışlı örnek olur bir sınıfın) ve aynı yapmak için bu nesnenin metodlarını çağırır.

Örnek olarak, PDO'de olmadan, böyle bir şey yapmak istiyorum:

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

Bu eşdeğer kullanılarak PDO olacaktır iken

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

Yani ilk bakışta, çok fark sözdizimi dışında, yoktur. Ama PDO sürümü bazı avantajları, büyük bir varlık veritabanı bağımsızlığı vardır:

Bunun yerine bir PostgreSQL veritabanına konuşmak gerekirse, sadece mysql: başlatmasını çağrısı pgsql: olarak değiştirmek istiyorum new PDO(). Eski yöntem ile, tüm 'mysql_doSomething ()' (her zaman parametre işlemedeki potansiyel farkları için kontrol) onların 'pg_doSomthing ()' meslektaşı ile işlevleri yerine, tüm kod geçmesi gerekiyor. Aynı durum diğer birçok desteklenen veritabanı motorları için durum olurdu.

Bazı kısayollar / gelişmeler / avantajlar sunarken Yani sorunuza geri almak için, PDO temelde sadece, sana aynı şeyleri elde etmek için farklı bir yol verir. Örneğin, öncelemeli kullandığınız veritabanı altyapısı için gerekli uygun şekilde otomatik olarak olur. Ayrıca parametre ikame (örneğin gösterilmeyen SQL iğneleri, engeller) daha az hata eğilimli hale çok daha kolaydır.

Diğer avantajları bir fikir edinmek için some OOP basics kadar okumalısınız.

Ben PDO ile süper aşina değilim, ama "hazırlanan tablolarda" kaçtı dizeleri arasında bir ayrım vardır. Kaçan sorgudan yaklaşık removing disallowed character strings, ancak hazırlanan tablolar telling the database what kind of query to expect üzeresiniz.

A query has multiple parts

Şöyle düşünün: Eğer veritabanına bir sorgu verdiğinizde, bunu birkaç ayrı şeyleri söylüyorsun. Bir şey, örneğin, "ben size bir seçme yapmak istiyorum." Olabilir Başka olacak "kullanıcı adı aşağıdaki değeri satırlara sınırlamak." Olabilir

Bir dize gibi bir sorgu oluşturmak ve veritabanına teslim Eğer tamamlanmış dize alır kadar, kısmen ya da bilmiyor. Bunu yapmak isteyebilirsiniz:

'SELECT * FROM transactions WHERE username=$username'

O dize alır, onu ayrıştırmak ve "bu bir SELECT bir WHERE ile" karar vermek zorundadır.

Getting the parts mixed up

Kötü niyetli bir kullanıcının billysmith OR 1=1 olarak kendi kullanıcı adını girer herhalde. Eğer dikkatli değilseniz, size sonuçlanan, dize içine koyabilirsiniz:

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

1 her zaman 1 eşittir çünkü ... ki, all the transactions for all users dönecekti. Whoops, sen kesmek oldum!

Ne oldu bakın? The database didn't know what parts to expect in your query, sadece dize çözümlü yani. Bu WHERE bunu tatmin olabilir iki koşul ile, bir OR vardı sürpriz değildi.

Keeping the parts straight

Bilindiği olsaydın what to expect, yani, bir SELECT olan WHERE, tek bir koşul vardı, kötü niyetli kullanıcı bunu kandırdın olamazdı.

Bir hazır deyimi ile, bunu bu doğru beklenti verebilir. Eğer "Sana bir SELECT göndermek üzereyim, ve ben sana vermek üzereyim satır WHERE username = bir dize ile sınırlı olacak veritabanı söyleyebilirim. Budur tüm - sorguya başka hiçbir parça yoktur Hazır hazır Tamam, burada adı karşılaştırmak için dize geliyor ".?.

Bu beklenti ile, veritabanı aldanmayın olacaktır: username sütun gerçek dize içeren nerede satırları döndürecektir 'billysmith OR = 1 1.' Kimse bu kullanıcı adı varsa, hiçbir şey dönecekti.

Other benefits of prepared statements

Güvenlik yardımlarına ek olarak, hazırlanan tablolar hız yararları bir çift var:

  • Onlar veritabanı zaten sormak için üzereyiz temelde ne biliyor çünkü, sıfırdan yeni bir sorgu bina daha hızlı olmalı farklı parametreler ile yeniden kullanılabilir. Zaten onun "sorgu planı" inşa etti.
  • Bazı veritabanları (Postregs bence, biri) kısa sürede hazırlanmış deyimi almak gibi bir sorgu planı yapma başlayacak - aslında onunla kullanılacak parametreleri yolladım önce. Yani, hatta ilk sorguda bir hıza görebilirsiniz.

Başka bir açıklama için, Theo'nun cevabı görmek here.

Mysql_real_escape_string aksine, PDO bir veri türü uygulamak için izin verir.

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

Yukarıdaki örnekte unutmayın, ilk parametre, kalori, bir tamsayı (PDO :: PARAM_INT) olması gerekmektedir.

İkincisi, benim için, PDO parametreli sorgular okumak kolaydır. Ben daha çok okurdum:

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

göre

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

Üçüncü olarak, size doğru parametreleri alıntı emin olmak zorunda değilsiniz. PDO o ilgilenir. Örneğin, mysql_real_query_string:

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

vs

SELECT * FROM user WHERE name = ?

Son olarak, PDO app PHP veri aramaları değiştirmeden farklı bir db port yapmanıza olanak sağlar.

Eğer satırlar boyunca bir şey yazmak hayal:

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

$ id 1 OR 1=1 olabilir, çünkü bu, enjeksiyon kurtaracak olmaz ve tablosundan tüm kayıtları alırsınız. Eğer (int bu durumda) doğru veri türüne $ id döküm olurdu

pdo başka bir avantaja sahiptir ve bu veritabanı artalanının birbiri arasında olduğunu.

SQL enjeksiyon önleme ek olarak, PDO kez bir sorgu hazırlamak ve bunu birden çok kez çalıştırmak için izin verir. Sorgu (örneğin, bir döngü içinde) birden çok kez idam edilirse, bu yöntem (ki her zaman MySQL eski sürümlerinde böyle değil gibi görünüyor çünkü ben, "olmalı" demek) daha verimli olmalıdır. Hazırlamak / bağlama yöntemi daha ben çalıştım diğer diller ile de uyumludur.

Neden PDO mysql_real_escape_string daha MySQL sorgular / querystrings kaçmak için daha iyi?

Simply because "escaping" alone makes no sense.
Moreover, it's different incomparable matters.

The only problem with escaping is that everyone takes it wrong, assuming it as some sort of "protection".
Everyone says "I escaped my variables" with the meaning "I protected my query".
While escaping alone has nothing to do with protection at all.

Koruma kabaca I escaped and quoted my data durumunda elde edilebilir, ancak (Bu arada, yanı sıra PDO), örneğin tanımlayıcılar için, her yerde geçerli değildir.

Yani, cevap:

  • PDO, binded değerler için kaçan yaparken, kaçan ama aynı zamanda alıntı değil geçerlidir - bu daha iyi olmasının nedeni bu.
  • "Kaçış" "koruma" ile eşanlamlı değildir. Kabaca isimli "kaçan + alıntı".
  • ancak her iki yöntem uygulanamaz bazı sorgu parçalar için.