sql >> Database teknologi >  >> RDS >> Mysql

Implementering af et konfigurerbart sammenføjningssystem, sikkert

Du gør så meget rigtigt, at jeg faktisk føler mig skyldig ved at påpege, at du gør noget forkert! :)

Du kan kun bruge forberedte sætninger til at parametrere feltværdier – ikke SQL-id'er såsom kolonne- eller tabelnavne. Derfor vil du ikke være i stand til at videregive A.x , B.z osv. ind i din JOIN kriterier ved hjælp af forberedte erklæringsparametre:du skal gør i stedet det, der føles frygteligt forkert, og sæt dem direkte sammen i din SQL-streng.

Alt er dog ikke tabt. I en eller anden vag præferencerækkefølge kan du:

  1. Præsenter brugeren en valgliste, hvorfra du efterfølgende samler SQL'en:

    <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>
    

    Derefter din formularbehandler:

    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";
    

    Denne tilgang har den fordel, at bortset fra at kompromittere PHP (i hvilket tilfælde du vil have langt større bekymringer end SQL-injektion), kan vilkårlig SQL absolut ikke finde vej til dit RDBMS.

  2. Sørg for, at brugerinputtet matcher en af ​​de forventede værdier:

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

    Derefter din formularbehandler:

    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]";
    

    Denne tilgang er afhængig af PHP's in_array funktion for sikkerheden (og afslører også dine underliggende kolonnenavne for brugeren, men givet din ansøgning tvivler jeg på, at det er en bekymring).

  3. Udfør noget inputrensning, såsom:

    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']) . '`'
    

    Selvom vi her citerer brugerens input og erstatter ethvert forsøg fra brugeren på at flygte fra det citat, kan denne tilgang være fuld af alle mulige fejl og sårbarheder (i enten PHP's mb_ereg_replace funktion eller MySQL's håndtering af specialfremstillede strenge inden for en citeret identifikator).

    Det er langt bedre hvis overhovedet muligt at bruge en af ​​ovenstående metoder for helt at undgå at indsætte brugerdefinerede strenge i ens SQL.



  1. Hvordan implementerer man én-til-en, én-til-mange og mange-til-mange relationer, mens man designer tabeller?

  2. ORA-00932:inkonsistente datatyper:forventet - fik CLOB

  3. MySQL-forespørgsel smertefuldt langsom på store data

  4. Venstre polstring i SQL Server – 3 LPAD()-ækvivalenter