2010-01-19 29 views
13

Tôi cố gắng để lắp ráp các câu lệnh SQL sau đây sử dụng db-api python của:làm thế nào để tạo ra một cách an toàn một câu lệnh SQL như sử dụng python db-api

SELECT x FROM myTable WHERE x LIKE 'BEGINNING_OF_STRING%'; 

nơi BEGINNING_OF_STRING nên một var python để được lấp đầy một cách an toàn trong thông qua DB-API. Tôi đã thử

beginningOfString = 'abc' 

cursor.execute('SELECT x FROM myTable WHERE x LIKE '%s%', beginningOfString) 
cursor.execute('SELECT x FROM myTable WHERE x LIKE '%s%%', beginningOfString) 

Tôi hết ý tưởng; cách chính xác để làm điều này là gì?

Trả lời

20

Tốt nhất là để tách các thông số từ sql nếu bạn có thể. Sau đó, bạn có thể để mô-đun db xử lý các trích dẫn thích hợp của các tham số.

sql='SELECT x FROM myTable WHERE x LIKE %s' 
args=[beginningOfString+'%'] 
cursor.execute(sql,args) 
+0

@ ~ unutbu: cảm ơn, móng tay đó. Đã không vượt qua tâm trí của tôi để chỉ cần gắn thêm% vào chính chuỗi * trước * truyền nó như một arg thông qua db-api. – laramichaels

2

EDIT:

Như Brian và Thomas ghi chú khác, các xa tốt hơn cách để làm điều này sẽ được sử dụng:

beginningOfString += '%' 
cursor.execute("SELECT x FROM myTable WHERE x LIKE ?", (beginningOfString,)) 

từ phương pháp đầu tiên để lại cho bạn mở các cuộc tấn công SQL injection .


trái ở cho lịch sử:

Hãy thử:

cursor.execute("SELECT x FROM myTable WHERE x LIKE '%s%%'" % beginningOfString) 
+3

-1 '" CHỌN x TỪ myTable KHI x LIKE '% s %%' "%" doom '; thả bảng x; chọn' "' ** Rất tiếc? ** – Brian

+0

@Brian; điểm rất hợp lệ! Tôi đã tập trung vào lỗi cú pháp; Tôi không nên giả định rằng 'đầu' là dữ liệu sạch. Cảm ơn vì đã bắt! –

+0

-1 đã bị xóa. Tuy nhiên, bạn vẫn có lỗi cú pháp. Sử dụng dấu ngoặc kép cho chuỗi của bạn và bạn sẽ không cần phải thoát khỏi dấu nháy đơn của bạn. – Brian

-1

Hãy lưu ý của Sqlite3 tài liệu:

Thông thường hoạt động SQL của bạn sẽ cần sử dụng giá trị từ biến Python. Bạn không nên tập hợp truy vấn của mình sử dụng các hoạt động chuỗi của Python vì làm như vậy không an toàn; nó làm cho chương trình của bạn dễ bị tấn công SQL tiêm.

Thay vào đó, hãy sử dụng tham số thay thế của DB-API. Đặt ? với tư cách trình giữ chỗ bất cứ nơi nào bạn muốn sử dụng giá trị và sau đó cung cấp một bộ giá trị làm đối số thứ hai cho phương thức execute() của con trỏ là . (Khác cơ sở dữ liệu module có thể sử dụng một giữ chỗ khác nhau, chẳng hạn như% s hoặc:. 1) Đối với dụ:

# Never do this -- insecure! 
symbol = 'IBM' 
c.execute("... where symbol = '%s'" % symbol) 

# Do this instead 
t = (symbol,) 
c.execute('select * from stocks where symbol=?', t) 

# Larger example 
for t in [('2006-03-28', 'BUY', 'IBM', 1000, 45.00), 
      ('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00), 
      ('2006-04-06', 'SELL', 'IBM', 500, 53.00), 
     ]: 
    c.execute('insert into stocks values (?,?,?,?,?)', t) 

Tôi nghĩ rằng bạn muốn điều này:

cursor.execute('SELECT x FROM myTable WHERE x LIKE '%?%', (beginningOfString,)) 
+0

Không, điều đó sẽ làm điều sai trái. –

+0

@Thomas: Tại sao? Khác với thực tế là tôi đã sử dụng ''%?%'' Thay vì ''?%'' (Anh ta không hoàn toàn nhất quán trong truy vấn của mình mà anh ta muốn), tôi không thấy vấn đề gì. – Brian

+5

Vấn đề là? được thay thế bằng phiên bản * trích dẫn * của đối số thực tế mà bạn vượt qua. Vì vậy, ví dụ, ''; DROP TABLE x; SELECT '"(thông báo đơn * và * dấu ngoặc kép ở đó), bạn kết thúc với truy vấn này rõ ràng là xấu: SELECT x FROM myTable WHERE x LIKE'% '; DROP TABLE x ; CHỌN '%' –

Các vấn đề liên quan