126 votes

Pourquoi préférons-nous toujours utiliser des paramètres dans les instructions SQL?

Je suis très novice en matière de travail avec les bases de données. Maintenant, je sais écrire les commandes SELECT, UPDATE, DELETE et INSERT. Mais j'ai vu de nombreux forums où nous préférons écrire:

SELECT empSalary from employee where salary = @salary

...au lieu de :

SELECT empSalary from employee where salary = txtSalary.Text

Pourquoi préférons-nous toujours utiliser des paramètres et comment les utiliser ?

Je voulais connaître l'utilisation et les avantages de la première méthode. J'ai même entendu parler d'injection SQL mais je ne le comprends pas pleinement. Je ne sais même pas si l'injection SQL est liée à ma question.

145voto

Chad Levy Points 3333

Utiliser des paramètres aide à prévenir les attaques par injection SQL lorsque la base de données est utilisée en conjonction avec une interface de programme telle qu'un programme de bureau ou un site web.

Dans votre exemple, un utilisateur peut exécuter directement du code SQL sur votre base de données en élaborant des instructions dans txtSalary.

Par exemple, s'ils écrivaient 0 OU 1=1, le SQL exécuté serait

 SELECT empSalary de l'employé où le salaire = 0 ou 1=1

où tous les salaires d'employés seraient retournés.

De plus, un utilisateur pourrait exécuter des commandes bien pires contre votre base de données, y compris la supprimer s'ils écrivaient 0; Supprimer La Table employé:

SELECT empSalary de l'employé où le salaire = 0; Supprimer La Table employé

La table employé serait ensuite supprimée.


Dans votre cas, il semble que vous utilisiez .NET. Utiliser des paramètres est aussi simple que :

string sql = "SELECT empSalary de l'employé où le salaire = @salaire";

using (SqlConnection connection = new SqlConnection(/* informations de connexion */))
using (SqlCommand command = new SqlCommand(sql, connection))
{
    var salaireParam = new SqlParameter("salaire", SqlDbType.Money);
    salaireParam.Valeur = txtMoney.Text;

    command.Parameters.Ajouter(salaireParam);
    var résultats = command.ExecuteReader();
}

Dim sql As String = "SELECT empSalary de l'employé où le salaire = @salaire"
Utilisant connection comme Nouveau SqlConnection("chaîne de connexion")
    Utilisant command comme Nouveau SqlCommand(sql, connection)
        Dim salaireParam = Nouveau SqlParameter("salaire", SqlDbType.Money)
        salaireParam.Valeur = txtMoney.Text

        command.Parameters.Ajouter(salaireParam)

        Dim résultats = command.ExecuteReader()
    Fin Utilisation
Fin Utilisation

Modifier 2016-4-25 :

Comme le commentaire de George Stocker, j'ai modifié le code d'exemple pour ne pas utiliser AddWithValue. De plus, il est généralement recommandé d'encadrer les IDisposables dans des déclarations using.

86voto

NullUserException Points 42268

Vous avez raison, cela est lié à l'injection SQL, qui est une vulnérabilité permettant à un utilisateur malveillant d'exécuter des déclarations arbitraires contre votre base de données. Ce vieux favori comic XKCD illustre le concept :

Sa fille s'appelle Aide je suis coincé dans une usine de permis de conduire.


Dans votre exemple, si vous utilisez simplement :

var query = "SELECT empSalary from employee where salary = " + txtSalary.Text;
// et procédez à l'exécution de cette requête

Vous êtes exposé à une injection SQL. Par exemple, si quelqu'un entre txtSalary :

1; UPDATE employee SET salary = 9999999 WHERE empID = 10; --
1; DROP TABLE employee; --
// etc.

Lorsque vous exécutez cette requête, elle effectuera un SELECT et un UPDATE ou DROP, ou ce qu'ils voulaient. Le -- à la fin commente simplement le reste de votre requête, ce qui serait utile dans l'attaque si vous concaténiez quelque chose après txtSalary.Text.


La bonne manière est d'utiliser des requêtes paramétrées, par exemple (C#) :

SqlCommand query = new SqlCommand("SELECT empSalary FROM employee 
                                    WHERE salary = @sal;");
query.Parameters.AddWithValue("@sal", txtSalary.Text);

Avec cela, vous pouvez exécuter la requête en toute sécurité.

Pour des références sur la façon d'éviter l'injection SQL dans plusieurs autres langages, consultez bobby-tables.com, un site maintenu par un utilisateur SO.

12voto

Oleg Points 1236

En plus des autres réponses, il est nécessaire d'ajouter que les paramètres permettent non seulement de prévenir les injections SQL mais peuvent améliorer les performances des requêtes. Sql server met en cache les plans de requêtes paramétrées et les réutilise lors de l'exécution de requêtes répétées. Si vous ne paramétrez pas votre requête, alors sql server compilerait un nouveau plan à chaque requête (à quelques exceptions près) si le texte de la requête diffère.

Plus d'informations sur la mise en cache des plans de requêtes

4voto

Emaad Ali Points 853

En Sql, lorsque n'importe quel mot contient le signe @, cela signifie qu'il s'agit d'une variable et nous utilisons cette variable pour y attribuer une valeur et l'utiliser dans une zone de nombre sur le même script sql, car elle est uniquement restreinte au seul script. Alors que vous pouvez déclarer de nombreuses variables du même type et du même nom sur de nombreux scripts. Nous utilisons cette variable dans les procédures stockées car ce sont des requêtes pré-compilées et nous pouvons transmettre des valeurs dans ces variables à partir de scripts, de bureaux et de sites web pour plus d'informations, consultez Déclarer une variable locale, Procédure stockée Sql et injections sql.

Lisez également Protégez-vous des injections sql, cela vous guidera sur la façon de protéger votre base de données.

En espérant que cela vous aide à comprendre, posez-moi également toutes vos questions dans les commentaires.

4voto

Arvin Amir Points 109

Ancien message mais je voulais m'assurer que les nouveaux arrivants sont conscients des procédures stockées.

Mon avis ici est que si vous êtes capable d'écrire votre instruction SQL comme une procédure stockée, c'est de loin la meilleure approche. JE utilise toujours des procédures stockées et ne fais jamais de boucle à travers des enregistrements dans mon code principal. Par exemple: Table SQL > Procédures stockées SQL > IIS/Dot.NET > Classe.

Lorsque vous utilisez des procédures stockées, vous pouvez restreindre l'utilisateur à la permission EXECUTE seulement, réduisant ainsi les risques de sécurité.

Votre procédure stockée est intrinsèquement paramétrée, et vous pouvez spécifier des paramètres d'entrée et de sortie.

La procédure stockée (si elle renvoie des données via l'instruction SELECT) peut être accédée et lue exactement de la même manière que vous le feriez avec une instruction SELECT régulière dans votre code.

Elle s'exécute également plus rapidement car elle est compilée sur le serveur SQL.

Ai-je aussi mentionné que vous pouvez effectuer plusieurs étapes, par exemple mettre à jour une table, vérifier les valeurs sur un autre serveur de base de données, et puis une fois enfin terminé, renvoyer les données au client, tout sur le même serveur, sans interaction avec le client. C'est donc BEAUCOUP plus rapide que de coder cette logique dans votre code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X