2009-12-23 5 views
0

Je voudrais stocker une requête mySQL dans un fichier. Je prévois de devoir en remplacer certaines parties par des variables de mon programme.moyen plus facile d'évaluer une chaîne à partir du fichier?

J'ai joué avec la méthode 'eval' en ruby, et ça marche, mais ça fait un peu maladroit. En utilisant irb, j'ai fait ce qui suit.

>> val = 7 
=> 7 
>> myQuery = "select * from t where t.val = \#{val}" #escaped hash simulates reading it from file 
=> "select * from t where t.val = \#{val}" 
>> myQuery = eval "\"#{myQuery}\"" 
=> "select * from t where t.val = 7" 

Comme vous pouvez le voir, cela fonctionne! Mais pour que cela fonctionne, j'ai dû envelopper la variable 'myQuery' dans des guillemets échappés, et le tout semble un peu en désordre.

Existe-t-il un moyen plus simple?

Répondre

1

En général, vous ne devriez pas utiliser l'interpolation de chaîne pour construire des requêtes SQL. Cela vous laissera la porte ouverte aux attaques SQL injection, dans lesquelles quelqu'un fournit une entrée avec un guillemet fermant, suivi d'une autre requête. Par exemple, en utilisant votre exemple:

>> val = '7; DROP TABLE users;' 
=> "7; DROP TABLE users;" 
>> myQuery = "select * from t where t.val = \#{val}" 
=> "select * from t where t.val = \#{val}" 
>> eval "\"#{myQuery}\"" 
=> "select * from t where t.val = 7; DROP TABLE users;" 

Même sans entrée malveillant, vous pouvez simplement exécuter accidentellement le code que vous n'êtes pas l'intention de, si quelqu'un instance inclus guillemets dans leur entrée.

Il est également généralement recommandé d'éviter d'utiliser eval sauf en cas d'absolue nécessité; il est possible que si vous avez un bogue dans votre programme, quelqu'un puisse exécuter du code arbitraire en le faisant passer à eval, et cela rend le code moins maintenable puisque certains de vos codes source seront chargés à partir d'endroits autres que votre arborescence source habituelle.

Alors, comment faites-vous cela à la place? Les API de base de données incluent généralement une commande prepare, qui peut préparer l'exécution d'une instruction SQL. Dans cette instruction, vous pouvez inclure ? caractères, qui représentent les paramètres qui peuvent être substitués dans cette instruction. Vous pouvez ensuite appeler le execute sur l'instruction, en passant des valeurs pour ces paramètres, et ils seront exécutés en toute sécurité, sans que personne ne puisse exécuter une partie arbitraire de SQL.

Voici comment cela fonctionnerait dans votre exemple. Cela suppose que vous utilisez this MySQL/Ruby module; Si vous en utilisez un autre, il aura probablement une interface similaire, bien que ce ne soit pas exactement la même chose.

>> val = 7 
>> db = Mysql.new(hostname, username, password, databasename) 
>> query = db.prepare("select * from t where t.val = ?") 
>> query.execute(val) 
0

Vous pouvez utiliser des modèles ERB à la place - les lire à partir des fichiers et interpoler les variables (convertir les variables <% = quelque chose%> en valeurs réelles).

Here's the official doc, c'est assez complet et simple.

0

Vous pouvez utiliser printf comme syntaxe pour la chaîne de remplacement

"123 %s 456" % 23 # => "123 23 456" 

Cela ne fonctionne que si votre programme sait à l'avance quelles sont les variables à utiliser.

0

Pourriez-vous utiliser des requêtes paramétrées? Je ne sais pas comment le faire dans ruby, mais il s'agit essentiellement de marquer votre instruction SQL avec des commandes que SQL reconnaît sont remplacées par des paramètres qui sont envoyés en plus de votre instruction.

Ce lien pourrait aider: http://sqlite-ruby.rubyforge.org/sqlite3/faq.html#538670816

Questions connexes