Mysql
 sql >> Base de données >  >> RDS >> Mysql

Nom de colonne dynamique utilisant une instruction préparée + une requête sql avec une variable contenant 's

À droite. Nous ne pouvons pas fournir d'identifiants en tant que paramètres de liaison. Le nom de la colonne doit faire partie du texte SQL.

Nous pouvons incorporer dynamiquement le nom de la colonne dans le texte SQL avec quelque chose comme ceci :

  sql = "UPDATE diseaseinfo"
      + " SET `" + colname + "` = ?"
      + " WHERE companyname = 'mycom' AND diseaseName = ?";

Et fournissez des valeurs pour les deux paramètres de liaison restants

  preparedStmt.setString(1, attrData);
  preparedStmt.setString(2, medname);

Et vous avez tout à fait raison de vous préoccuper de l'injection SQL.

Fourni sous forme de valeurs de liaison, guillemets simples dans les valeurs de attrData et medname ne sera pas un problème, en termes d'injection SQL.

Mais l'exemple que j'ai fourni est vulnérable en incorporant le colname variable dans le texte SQL, si nous n'avons pas de garantie que colname est "sûr" à inclure dans la déclaration.

Il faut donc faire l'assignation d'une valeur à colname "sûr".

Plusieurs approches que nous pouvons utiliser le font. La plus sûre serait une approche "liste blanche". Le code peut garantir que seules des valeurs "sûres" autorisées spécifiques sont affectées à colname , avant colname est inclus dans le texte SQL.

Comme exemple simple :

  String colname;
  if (attributes.equals("someexpectedvalue") {
      colname = "columnname_to_be_used";
  } else if (attributes.equals("someothervalid") {
      colname = "valid_columname";
  } else {
     // unexpected/unsupported attributes value so
     // handle condition or throw an exception 
  }

Une approche plus flexible consiste à s'assurer qu'un caractère de backtick n'apparaît pas dans colname . Dans l'exemple, la valeur de colname est en cours d'évasion en l'entourant de backticks. Donc, tant qu'un caractère de backtick n'apparaît pas dans colname , nous empêcherons qu'une valeur fournie soit interprétée autrement que comme un identifiant.

Pour une approche plus générique (et compliquée) de l'utilisation de caractères de backtick codés en dur, nous pourrions envisager d'utiliser le supportsQuotedIdentifiers et getIdentifierQuoteString méthodes de java.sql.DatabaseMetaData classe.

(Dans le code OP, nous ne voyons pas le type de données du contenu des attributes . Nous voyons un appel à une méthode nommée replace , et les arguments qui lui sont fournis. En supposant que les attributes est une chaîne, et c'est censé être un nom de colonne, il n'est pas du tout clair pourquoi nous aurions "espace entre guillemets simples" dans la chaîne, ou pourquoi nous devons supprimer cela. À part cette mention, cette réponse ne traite pas de cela.)