2009-02-11 37 views
31

Tôi đang tái kỹ thuật một trang web hướng PHP sử dụng cơ sở dữ liệu tối thiểu. Phiên bản gốc được sử dụng "pseudo-prepared-statements" (các hàm PHP đã trích dẫn và thay thế tham số) để ngăn chặn các cuộc tấn công tiêm và tách logic cơ sở dữ liệu khỏi logic trang. Có vẻ như tự nhiên để thay thế các chức năng đặc biệt này bằng một đối tượng sử dụng PDO và các câu lệnh chuẩn bị thực sự, nhưng sau khi đọc xong, tôi không chắc lắm. PDO vẫn có vẻ như là một ý tưởng tuyệt vời, nhưng một trong những điểm bán hàng chính của các báo cáo chuẩn bị là có thể tái sử dụng chúng ... mà tôi sẽ không bao giờ làm. Đây là thiết lập của tôi:Khi * không * sử dụng câu lệnh đã chuẩn bị?

  • Các câu lệnh đều đơn giản giản dị. Hầu hết đều ở dạng SELECT foo,bar FROM baz WHERE quux = ? ORDER BY bar LIMIT 1. Câu lệnh phức tạp nhất trong lô chỉ đơn giản là ba lựa chọn như vậy được nối cùng với UNION ALL s.
  • Mỗi lần truy cập trang thực thi tối đa một tuyên bố và chỉ thực thi một lần.
  • Tôi đang ở trong một môi trường được lưu trữ và do đó, sự rùng rợn của các máy chủ của họ bằng cách thực hiện bất kỳ "kiểm tra căng thẳng" nào.

Do sử dụng câu lệnh chuẩn bị, tối thiểu, gấp đôi số lượng chuyến đi khứ hồi cơ sở dữ liệu tôi đang tạo, tôi có nên tránh chúng không? Tôi có thể sử dụng PDO::MYSQL_ATTR_DIRECT_QUERY để tránh chi phí cho nhiều chuyến đi cơ sở dữ liệu trong khi vẫn giữ được lợi ích của việc bảo vệ và phòng ngừa tiêm? Hoặc thực hiện các cuộc gọi nhị phân được API chuẩn bị đã sử dụng thực hiện đủ tốt so với thực hiện các truy vấn không được chuẩn bị mà tôi không nên lo lắng về nó?

EDIT:

Cảm ơn tất cả những lời khuyên tốt, folks. Đây là nơi tôi ước tôi có thể đánh dấu nhiều hơn một câu trả lời là "được chấp nhận" - nhiều quan điểm khác nhau. Cuối cùng, mặc dù, tôi phải cung cấp cho rick do của mình ... mà không có câu trả lời của mình tôi sẽ có blissfully đi tắt và thực hiện hoàn toàn sai điều thậm chí sau khi sau lời khuyên của mọi người. :-)

Phát biểu được mô phỏng được mô phỏng!

+3

** Cẩn thận **: PDO giả lập các câu lệnh được chuẩn bị dễ bị tấn công với SQL injection nếu bộ ký tự được thay đổi khi chạy. Xem [câu trả lời này] (http://stackoverflow.com/a/60496/1862009) và [câu trả lời này] (http://stackoverflow.com/a/12202218/1862009) để được giải thích. – toxalot

+0

Thật dễ dàng: Nếu bạn biết * chuỗi xuất phát từ ứng dụng của bạn và không thể bị người dùng thao tác, thì không cần phải có các câu lệnh chuẩn bị, bởi vì không có gì để tiêm. Nếu bạn không chắc chắn (xấu, nhưng trong các dự án lớn hơn không tránh được) sử dụng tuyên bố chuẩn bị. –

Trả lời

14

Tôi nghĩ bạn muốn PDO :: ATTR_EMULATE_PREPARES. Điều đó sẽ tắt các câu lệnh chuẩn bị cơ sở dữ liệu gốc, nhưng vẫn cho phép các ràng buộc truy vấn để ngăn chặn việc chèn sql và giữ cho ngăn xếp sql của bạn. Từ những gì tôi hiểu, PDO :: MYSQL_ATTR_DIRECT_QUERY tắt hoàn toàn truy vấn.

24

Quy tắc kỹ thuật phần mềm ngày nay: nếu không có ý định làm gì cho bạn, đừng sử dụng.

+5

+5 - Cá nhân tôi nghĩ áp lực * luôn luôn sử dụng các câu lệnh chuẩn bị sẵn sàng cho các chương trình giáo phái hàng hóa. – toxalot

2

Thành thật mà nói, tôi không nghĩ bạn nên lo lắng về điều đó. Tuy nhiên, tôi nhớ rằng một số khung truy cập dữ liệu PHP hỗ trợ các chế độ câu lệnh chuẩn bị và các chế độ câu lệnh không chuẩn bị. Nếu tôi nhớ chính xác, PEAR: DB đã trở lại trong ngày.

Tôi đã gặp vấn đề tương tự như bạn và tôi đã đặt chỗ của riêng mình, vì vậy thay vì sử dụng PDO, tôi đã viết lớp cơ sở dữ liệu trọng lượng nhẹ hỗ trợ chuẩn bị và báo cáo chuẩn và thực hiện thoát đúng cách (sql-injection) phòng ngừa) trong cả hai trường hợp. Một trong những cái kẹp khác của tôi với các chuẩn bị là đôi khi nó có hiệu quả hơn để gắn thêm một số đầu vào không thể thoát được vào một câu lệnh như ... WHERE id IN (1, 2, 3 ...).

Tôi không biết đủ về PDO để cho bạn biết các tùy chọn khác mà bạn có sử dụng nó. Tuy nhiên, tôi biết rằng PHP đã thoát khỏi các chức năng sẵn có cho tất cả các nhà cung cấp cơ sở dữ liệu mà nó hỗ trợ và bạn có thể cuộn lớp nhỏ của riêng mình lên trên bất kỳ lớp truy cập dữ liệu nào mà bạn đang mắc phải.

7

Báo cáo chuẩn bị đang được hàng nghìn người sử dụng và do đó được kiểm tra kỹ lưỡng (và do đó người ta có thể suy ra chúng an toàn hợp lý).Giải pháp tùy chỉnh của bạn chỉ được bạn sử dụng.

Cơ hội giải pháp tùy chỉnh của bạn không an toàn là khá cao. Sử dụng báo cáo đã chuẩn bị. Bạn phải duy trì mã ít hơn theo cách đó.

7

Những lợi ích của chuẩn bị phát biểu như sau:

  • mỗi truy vấn chỉ được biên soạn lần
  • mysql sẽ sử dụng một định dạng phương tiện giao thông hiệu quả hơn để gửi dữ liệu đến máy chủ

Tuy nhiên, câu lệnh chuẩn bị chỉ tồn tại trên mỗi kết nối. Trừ khi bạn đang sử dụng kết nối tổng hợp, sẽ không có lợi ích nếu bạn chỉ làm một tuyên bố trên mỗi trang. Truy vấn đơn giản trivially sẽ không được hưởng lợi từ các định dạng vận chuyển hiệu quả hơn, một trong hai.

Cá nhân tôi sẽ không bận tâm. Các câu lệnh giả được chuẩn bị có thể hữu ích cho các biến an toàn trích dẫn mà họ cho là có thể cung cấp.

+1

Bạn đã bỏ lỡ một: trích dẫn dữ liệu thông minh đến nó. – Powerlord

+6

Missed one, nhưng không phải là một. Các tham số cho các câu lệnh đã chuẩn bị được chuyển tới máy chủ db thông qua một kênh riêng biệt (nghĩa là không phải là một phần của câu lệnh SQL), vì vậy chúng không cần phải được thoát vì chúng đang truy cập dữ liệu, chứ không phải là một lệnh tiềm năng. –

+1

Nó không thay đổi bất cứ điều gì về hiệu quả, hoặc nó là một chút tồi tệ hơn. SQL được biên dịch trên máy chủ chứ không phải trên máy khách.Vì vậy, khi bạn gửi một câu lệnh đã chuẩn bị với các tham số bị ràng buộc, bạn thực sự gửi nhiều gói đến máy chủ (một cho chỉ số chuẩn, một cho các tham số), do đó nó thêm độ trễ. Tuy nhiên, nếu bạn sử dụng lại câu lệnh chuẩn bị của mình, thì đó là số tiền kiếm được vì bạn tiết kiệm thời gian biên dịch cho bản kê khai và chỉ trả tiền phạt để gửi các tham số. – xryl669

14

Khi không để sử dụng báo cáo đã chuẩn bị? Khi bạn sẽ chỉ chạy câu lệnh một lần trước khi kết nối db biến mất.

Khi không để sử dụng tham số truy vấn bị ràng buộc (thực sự điều mà hầu hết mọi người sử dụng câu lệnh chuẩn bị để nhận)? Tôi muốn nói "không bao giờ" và tôi thực sự muốn nói "không bao giờ", nhưng thực tế là hầu hết các cơ sở dữ liệu và một số lớp trừu tượng db có những trường hợp nhất định, theo đó chúng sẽ không cho phép bạn ràng buộc các tham số, vì vậy bạn buộc phải không sử dụng chúng trong những trường hợp đó. Bất cứ lúc nào, mặc dù, nó sẽ làm cho cuộc sống của bạn đơn giản hơn và mã của bạn an toàn hơn để sử dụng chúng.

Tôi không quen với PDO, nhưng tôi đặt cược nó cung cấp một cơ chế để chạy truy vấn parametrized với các giá trị được đưa ra trong cùng một hàm gọi nếu bạn không muốn chuẩn bị, sau đó chạy như một bước riêng biệt. (ví dụ: Cái gì đó giống như run_query("SELECT * FROM users WHERE id = ?", 1) hoặc tương tự.)

Ngoài ra, nếu bạn nhìn vào nắp, hầu hết các lớp trừu tượng của DB2 sẽ chuẩn bị truy vấn, sau đó chạy nó, ngay cả khi bạn chỉ cần thực hiện câu lệnh SQL tĩnh. Vì vậy, bạn có thể không tiết kiệm một chuyến đi đến db bằng cách tránh rõ ràng chuẩn bị dù sao đi nữa.

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