2012-06-07 24 views
5

nềnThực hiện một "cấu hình" hệ thống tham gia, an toàn

Xin chào, tôi đang phát triển một công cụ giáo dục/thực nghiệm trong PHP và MySQL. Tôi mới sử dụng SQL, nhưng tôi muốn làm mọi thứ ngay từ đầu. Tôi đang sử dụng PDO chuẩn bị báo cáo cho tất cả thay thế biến, và backticking ở khắp mọi nơi có thể (vì vậy, như tôi hiểu, nó sẽ không được di động để cơ sở dữ liệu không MySQL). Về vấn đề của tôi, tôi có một ý tưởng như thế nào để đi ra ngoài, nhưng nó sẽ đưa tôi vài giờ để thực hiện (tôi mới ngay cả với cú pháp của SQL), vì vậy trong khi đó tôi nghĩ rằng tôi muốn tạo ra một câu hỏi đầu tiên trong trường hợp ai đó có thể la lên, "Đây không phải là cách để làm điều đó!" và tiết kiệm cho tôi nhiều giờ nỗ lực.

Vấn đề

Tôi muốn tạo ra một giao diện mà một người dùng sẽ chọn từ trình đơn thả xuống:

  1. một bảng A,
  2. một hoặc nhiều lĩnh vực trên bàn đó, ví dụ A.xA.y,
  3. một bảng B,
  4. một hoặc nhiều trường trên bảng đó, ví dụ: B.zB.y,

và khi gửi mã sẽ thực hiện tham gia bên trong, khớp với từng trường tương ứng, ví dụ: A.x = B.z, A.y = B.y, v.v. và trả về tất cả các hàng phù hợp.

Kế hoạch của tôi chỉ đơn giản là tạo ra một câu lệnh SQL INNER JOIN, lặp qua các trường và chèn trình giữ chỗ (?), ràng buộc các tham số tương ứng và cuối cùng thực thi câu lệnh.

Có cách nào dễ dàng hơn để thực hiện việc này không? Có cách nào tốt hơn để làm điều này? Điều này sẽ được khai thác bằng cách nào đó?

Cảm ơn bạn rất nhiều, trước. Nếu không ai trả lời vào thời điểm tôi hoàn thành (nghi ngờ), tôi sẽ đăng giải pháp của mình.

Misc.

Giả sử rằng tôi sẽ xác nhận

  1. mà người sử dụng chọn một số lượng tương đương các trường giữa AB,
  2. rằng các lĩnh vực và bảng tồn tại,
  3. , vv

và rằng tên trường không cần phải giống nhau: chúng sẽ được khớp theo thứ tự. (Đừng chỉ ra bất kỳ chi tiết nào khác mà tôi có thể không biết!)

Cuối cùng, mục tiêu là để các lựa chọn này được lưu trong bảng "cài đặt". Thực tế, người dùng tạo "lượt xem" mà họ muốn xem mỗi khi họ quay lại.

+0

+1 câu hỏi thực sự mang tính thông tin ... cách để thực hiện. – Wh1T3h4Ck5

Trả lời

2

Bạn đang làm rất nhiều điều mà tôi thực sự cảm thấy tội lỗi chỉ ra rằng bạn đang làm điều gì đó sai trái! :)

Bạn chỉ có thể sử dụng câu lệnh đã chuẩn bị để tham số giá trị tham số — không phải số nhận dạng SQL như tên cột hoặc bảng. Do đó, bạn sẽ không thể vượt qua A.x, B.z v.v. vào tiêu chí JOIN của mình theo các thông số tuyên bố đã chuẩn bị: bạn phải thay vì thực hiện những gì gây nhầm lẫn và trực tiếp nối chúng vào chuỗi SQL của bạn.

Tuy nhiên, tất cả đều không bị mất. Trong một số mệnh lệnh mơ hồ sở thích, bạn có thể:

  1. hiện tại người dùng với một danh sách tùy chọn, từ đó bạn sau đó lắp ráp lại các SQL:

    <select name="join_a"> 
        <option value="1">x</option> 
        <option value="2">y</option> 
    </select> 
    <select name="join_b"> 
        <option value="1">z</option> 
        <option value="2">y</option> 
    </select> 
    

    Sau đó, hình thức của bạn xử lý:

    switch ($_POST['join_a']) { 
        case 1: $acol = 'x'; break; 
        case 2: $acol = 'y'; break; 
        default: die('Invalid input'); 
    } 
    switch ($_POST['join_b']) { 
        case 1: $bcol = 'z'; break; 
        case 2: $bcol = 'y'; break; 
        default: die('Invalid input'); 
    } 
    
    $sql .= "FROM A JOIN B ON A.$acol = B.$bcol"; 
    

    Cách tiếp cận này có lợi thế là, không ảnh hưởng đến PHP (trong trường hợp này bạn sẽ có mối quan tâm lớn hơn nhiều so với SQL injection), SQL tùy ý hoàn toàn không thể tìm đường vào RDBMS của bạn.

  2. Đảm bảo đầu vào dùng phù hợp với một trong những giá trị mong đợi:

    <select name="join_a"> 
        <option>x</option> 
        <option>y</option> 
    </select> 
    <select name="join_b"> 
        <option>z</option> 
        <option>y</option> 
    </select> 
    

    Sau đó, hình thức xử lý của bạn:

    if (!in_array($_POST['join_a'], ['x', 'y']) 
    or !in_array($_POST['join_b'], ['z', 'y'])) 
        die('Invalid input'); 
    
    $sql .= "FROM A JOIN B ON A.$_POST[join_a] = B.$_POST[join_b]"; 
    

    Cách tiếp cận này dựa trên in_array chức năng của PHP cho sự an toàn (và cũng cho thấy nhiều đến sử dụng tên cột cơ bản của bạn, nhưng với ứng dụng của bạn, tôi nghi ngờ đó là một mối quan tâm).

  3. Thực hiện một số thanh lọc đầu vào, chẳng hạn như:

    mb_regex_encoding($charset); // charset of database connection 
    $sql .= 'FROM A JOIN B ON A.`' . mb_ereg_replace('`', '``', $_POST['join_a']) . '`' 
            . ' = B.`' . mb_ereg_replace('`', '``', $_POST['join_b']) . '`' 
    

    Trong khi chúng tôi ở đây trích dẫn đầu vào người sử dụng và thay thế bất kỳ nỗ lực của người sử dụng để thoát khỏi rằng trích dẫn, phương pháp này có thể là đầy đủ của tất cả các loại lỗ hổng và các lỗ hổng (trong chức năng mb_ereg_replace của PHP hoặc xử lý các chuỗi được tạo đặc biệt của MySQL trong một mã định danh được trích dẫn).

    Đó là xa tốt hơn nếu có thể sử dụng một trong các phương pháp trên để tránh chèn chuỗi do người dùng xác định vào SQL của một người hoàn toàn.

+0

Cảm ơn vì những lời khích lệ; thậm chí nhiều hơn cho một câu trả lời toàn diện như vậy. Có, cuối cùng tôi nhận ra định danh không thể được parametrised, và sau khi một số trình duyệt tôi bắt đầu nghi ngờ nối có thể là cách duy nhất. Vì vậy, tôi đặt nó xuống và đi ngủ, hy vọng một người nào đó biết một cách tốt hơn so với kiểm tra thực địa từng trường. Thật không may như bạn chỉ ra, có vẻ như không được! Nhưng tôi rất vui vì tôi có thể tiến về phía trước một cách tự tin. Tôi thấy lợi thế của sở thích [1], tuy nhiên tôi muốn _like_ người dùng nhìn thấy tên cột, vì vậy tôi sẽ đi với [2]. (Và [3] sẽ giữ tôi vào ban đêm.) Cảm ơn một lần nữa! –

1

Giả sử rằng đầu vào của người dùng bị giới hạn chỉ chọn các bảng và trường (tức làkhông có điều kiện bổ sung), bạn nên sử dụng phương pháp tiếp cận của mình; nghe có vẻ thú vị :)

Một điều tôi muốn thêm là một số kết nối nhất định tốt hơn các kết nối khác. Ví dụ, việc tham gia hai bảng bằng cách sử dụng các khóa chính của chúng (hoặc các chỉ mục khác) sẽ thực hiện tốt hơn hai cột không liên quan với yêu cầu quét toàn bộ bảng.

Tất cả điều này phụ thuộc vào mức độ lớn của các bảng ở nơi đầu tiên; cho ít hơn một vài nghìn hồ sơ, bạn sẽ không sao; bất cứ điều gì vượt ra ngoài suy nghĩ nghiêm túc được đặt ra :)

+1

Không thể tham số hóa số nhận dạng ... – eggyal

+0

@eggyal ah, cũng vậy :) cũng phát hiện ra! –

+0

Cảm ơn; điều này có vẻ như một phần là một phiên bản nhỏ gọn của câu trả lời tôi chấp nhận - xin lỗi tôi đã phải đưa nó cho anh chàng/cô gái khác. Có, có vẻ như tôi sẽ phải hiển thị và kiểm tra tên bảng và trường. Điểm tốt về hiệu quả của gia nhập. Vì đây là một phần công cụ giáo dục, tôi thực sự muốn để lại chi tiết đó cho người dùng để quản lý, nhưng tôi chắc chắn sẽ tạo chú thích giải thích tầm quan trọng của các khóa chính và chỉ mục (chỉ mục?). –

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