L'injection SQL est une méthode d'attaque très simple, mais elle est toujours très commune à ce jour. La raison n'est rien de plus: pas de patch pour stupide. Pourquoi dites-vous cela? Prenons Java comme exemple pour illustrer:
Supposons qu'il y ait une table comme celle-ci dans la base de données:
Tableau utilisateur (id varchar (20) Clé primaire, nom varchar (20), âge varchar (20));
Utilisez ensuite JDBC pour faire fonctionner le tableau:
String privé getNameByUserId (String userId) {connexion conn = getConn (); // get connection String sql = "select name from User where id =" + userId; Préparé Pstmt = Conn.PrepareStatement (SQL); ResultSet rs = pstmt.ExecuteUpdate (); ......}Le code ci-dessus est souvent utilisé par certains développeurs. Imaginez cette situation, lorsque le paramètre UserId passé est "3; Drop Table User;", l'instruction SQL exécutée est la suivante:
Sélectionnez le nom de l'utilisateur où id = 3; Utilisateur de table de dépression;
Une fois la base de données compilée et exécutée, le tableau utilisateur est supprimé. Regardez, une simple attaque d'injection SQL est en vigueur! En effet, le code ci-dessus ne respecte pas les spécifications de programmation.
L'injection SQL n'existe pas lorsque nous programmons selon les spécifications. C'est également la première façon d'éviter l'injection SQL: instructions précompilées, le code est le suivant:
Connexion conn = getConn (); // obtenir la chaîne de connexion sql = "select name from User où id =?"; Préparé Pstmt = Conn.PrepareStatement (SQL); PSTMT.SetString (1, UserId); ResultSet rs = pstmt.ExecuteUpdate (); ....
Pourquoi l'injection SQL n'existe-t-elle pas dans le code ci-dessus? Étant donné que les instructions précompilées sont utilisées, l'instruction précompilée compilera le "Sélectionner le nom de l'utilisateur où id =?" Instruction à l'avance lors de l'exécution, donc lors de l'exécution, il vous suffit de le remplacer par les paramètres passés? Espace réservé. Pour le premier cas qui ne respecte pas les spécifications, le programme créera des instructions SQL, puis les compilera avec le contenu transmis par l'utilisateur. C'est exactement le problème.
En plus d'utiliser des instructions précompilées, il existe une deuxième façon d'éviter les attaques d'injection SQL: procédures stockées. La procédure stockée est un ensemble d'instructions SQL qui remplissent des fonctions spécifiques. Après compilation, il est stocké dans la base de données. Les utilisateurs peuvent l'exécuter en appelant des procédures stockées et en donnant des paramètres (si la procédure stockée a des paramètres) et peut également éviter les attaques d'injection SQL.
Connexion conn = getConn (); stmt = conn.prepareCall ("{appel name_from_user (?,?)}"); stmt.sentInt (1,2); STMT.RegisterOutParameter (2, types.varchar); stmt.execute (); String name = stmt.getString (2);Les procédures stockées correspondantes dans le code ci-dessus sont les suivantes:
utiliser l'utilisateur; Delimiter // Créer la procédure Nom_From_User (dans user_id int, out user_name varchar (20)) commencez le nom dans user_name dans l'utilisateur où id = user_id; fin // délimiteur;
Bien sûr, les utilisateurs peuvent également effectuer une vérification des caractères sur l'avant, ce qui est également un moyen d'éviter l'injection SQL: par exemple, pour le paramètre utilisateur ci-dessus, l'utilisateur invitera une erreur lors de la vérification que le point-virgule est inclus.
Cependant, à partir de la raison la plus fondamentale, l'attaque d'injection SQL existe car l'application n'utilise pas les autorisations minimales lors de l'accès à la base de données. Je pense que oui, il semble que tout le monde utilise le compte racine pour accéder à la base de données.
Alors, comment MyBatis évite-t-il les attaques d'injection SQL? Utilisons l'utilisateur de la table ci-dessus comme exemple:
Supposons que le fichier de mappeur est:
<select id = "getNameByUserId" resultType = "String"> Sélectionnez Nom dans l'utilisateur où id = # {userId} </lect>Le fichier Java correspondant est:
interface publique userMapper {String getNameByUserId (@param ("userId") String userId); }Vous pouvez voir que le paramètre d'entrée est utilisateur de type de chaîne. Lorsque nous passons userId = "34; Drop Table User;" La déclaration imprimée est la suivante:
Sélectionnez le nom de l'utilisateur où id =?
Peu importe ce que l'utilisateur est entré, ses instructions SQL sont comme ceci. Cela est dû à l'utilisation de déclarations précompilées dans l'implémentation sous-jacente. Lorsque la base de données exécute cette instruction, elle utilise directement l'instruction précompilée, puis remplace l'espace réservé par l'UserID passé? Allez courir. N'existe pas pour remplacer l'espace réservé en premier? Le processus de compilation est effectué, il n'y a donc pas de place pour la survie pour l'injection SQL.
Alors, comment MyBatis réalise la pré-compilation de SQL? En fait, le cadre utilise la classe PreadStatement. La classe de préparation de préparation évite non seulement l'injection SQL, car elle a été précompilée. Lorsque la même instruction SQL est exécutée n fois, elle économise (N-1) le temps de compilation, améliorant ainsi l'efficacité.
Si vous modifiez la déclaration ci-dessus:
<select id = "getNameByuserid" resultType = "String"> Sélectionnez Nom dans l'utilisateur où id = $ {userId} </lect> Lorsque nous entrons dans userId="34;drop table user;" , la déclaration imprimée ressemble à ceci:
Sélectionnez le nom de l'utilisateur où id = 34; déposez l'utilisateur de la table;
À l'heure actuelle, MyBatis n'utilise pas de déclarations précompilées. Il effectuera d'abord des coutures de chaîne, puis effectuera la compilation. Ce processus est le processus d'injection SQL.
Par conséquent, lorsque vous écrivez des instructions de mappage MyBatis, essayez d'utiliser le format "# {xxx}". Si vous devez utiliser des paramètres comme "$ {xxx}", vous devez faire manuellement un bon travail de filtrage pour éviter les attaques d'injection SQL.
Résumer
Ce qui précède est une explication détaillée de la méthode de prévention de l'injection SQL par Mybatis qui vous a été présentée. J'espère que cela vous sera utile. Si vous avez des questions, veuillez me laisser un message et l'éditeur vous répondra à temps. Merci beaucoup pour votre soutien au site Web Wulin.com!