MySQL'e bağlanmak ve sorguları yürütmek için Python en iyi uygulama ve en güvenli

MySQL ve SQL enjeksiyonu ile ilgili tehlikelerin farkındayım MySQL sorguları çalıştırmak için en güvenli yolu nedir.

Ancak, diğer kullanıcıların (webclients) manipüle edebileceği değişkenlere enjeksiyon yapılmasını önlemek için sorgularımı nasıl çalıştırmam gerektiğini bilmiyorum. Kendi kaçış işlevimi yazıyordum, ama görünüşe göre bu "yapılmadı".

Ne kullanmalıyım ve MySQL veritabanında MySQL enjeksiyon riski olmadan python üzerinden güvenli bir şekilde sorgulamak ve eklemek için ne kullanmalıyım?

42

3 cevap

Enjeksiyonlardan kaçınmak için execute komutunu % s ile her değişkenin yerine kullanın, sonra değeri bir listeden geçirin veya çalıştır . İşte, bir dokümantasyondan bir örnek :

c=db.cursor()
max_price=5
c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""", (max_price,))

Bunun % değil, bir virgül kullandığını unutmayın (bu, kaçan dizgeyi değiştirmeyecek, kaçma değil). Bunu yapma :

c.execute("""SELECT spam, eggs, sausage FROM breakfast
          WHERE price < %s""" % (max_price,))

Ek olarak, parametre bir dizge ise, konum tutucu ( '% s' ) çevresindeki tırnaklara ihtiyacınız yoktur.

62
katma
ve tam sayı olduğunda?
katma yazar Lucas Kauffman, kaynak
max_price'nin arkasında neden bir virgül var? Ne anlama geliyor ? Üzgünüm, sorularım hayırlı görünüyorsa, ama python için oldukça yeniyim :)
katma yazar Lucas Kauffman, kaynak
Siz bunun bir virgül kullandığını unutmayın,% değil (bu, doğrudan bir dizge değiştirme olur, kaçılmaz). Bunu yapma Emin misiniz? Çünkü virgül kullandım ve dizeden kaçıyor
katma yazar Hussain, kaynak
@Bruno Oh! Anladım. Bu yüzden doğru yolu yapıyorum. Bu arada beni affet. Yanlış anladım.
katma yazar Hussain, kaynak
% s 'ı da kullanın (yukarıdaki max_price örneğine bakın).
katma yazar Bruno, kaynak
max_price 'den sonraki koma, 1 öğeli bir tuple için göstergedir: docs.python.org/tutorial/…
katma yazar Bruno, kaynak
@HussainTamboli, evet, tam olarak söylediğim şey: virgül, parametre yer tutucularını kullanmanın doğru yoludur (tüm kaçış gerekli), % parametrelerden kaçamaz.
katma yazar Bruno, kaynak
Python, değerleri, MySQL'in anladığı ve gerekli teklifleri eklediği bir veri türüne dönüştürür.
katma yazar shadow0359, kaynak

Bruno'nun cevabının bir uzantısı olarak, MySQL istemci kitaplığınız, adlandırılmış parametreler belirtmek için birkaç farklı formattan birini destekleyebilir. PEP 249 (DB-API) 'dan aşağıdaki gibi sorularınızı yazabilirsiniz:

'Qmark'

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = ?", (lumberjack,))

'Sayısal'

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = :1", (lumberjack,))

'Adlı'

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = :jack", {'jack': lumberjack})

'biçim'

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = %s", (lumberjack,))

'Pyformat'

>>> cursor.execute("SELECT spam FROM eggs WHERE lumberjack = %(jack)s", {'jack': lumberjack})

İstemci kitaplığınızın, paramstyle modül düzeyi değişkenine bakarak destekleyebileceğini görebilirsiniz:

>>> clientlibrary.paramstyle
'Pyformat'

Yukarıdaki seçeneklerden herhangi biri, güvensiz verilerinizi ele alma konusunda Doğru Olanı yapmalıdır. Bruno'nun belirttiği gibi, lütfen asla parametreleri eklemeyi denemeyin. Yaygın olarak kullanılan istemci kitaplıkları, verileri fanilerin hiçbir zaman olamayacağından daha doğru bir şekilde işlemede çok daha iyidir.

61
katma
Hangi istemci kütüphaneleri 'adlandırılmış'? PyMySQL ve MySQLdb desteği 'format' ve oursql 'qmark'ı destekler.
katma yazar Martin Burch, kaynak
sqlite3 en azından 'named' özelliğini destekler. İçinde 'adlandırılmış' desteği olup olmadığını kontrol etmek için herhangi bir MySQL bağdaştırıcım yok.
katma yazar Kirk Strauser, kaynak
Bu sadece kendi başına yeterince iyi. Ben son derece, bir ORM gibi SQLAlchemy kontrol ve tavsiye sizin için ayrıntıları ele icar tavsiye ederim.
katma yazar Kirk Strauser, kaynak
Bunun eski bir soru olduğunu biliyorum, ancak web sayfamı düzgün şekilde kodlamaya çalışıyorum ve güvenli SQL'de çok fazla deneyimim yok. Yukarıda açıklanan bu yöntemi kullanarak SQL Enjeksiyonunu önlemede yeterli mi, yoksa buna ek olarak yapmam gereken başka şeyler var mı? Teşekkürler.
katma yazar jonesy19, kaynak

Eğer mysqldb kullanıyorsanız, dahili escape_string işlevini kullanabilirsiniz. Bunun gibi.

sql = "SELECT spam FROM eggs WHERE lumberjack = '" + MySQLdb.escape_string(str(lumberjack)) + "';"
cursor.execute(sql)

Her zaman veritabanı bağlayıcısının kaçış işlevini kullanmayı tercih ederim - amaçlanan ve elle kodlama kaçış işlevlerinin kendisinde bir güvenlik riski olduğu gibi çalışır.

0
katma