Dans la première
partie de ce tutoriel dédié aux erreurs à
ne pas commettre en Php, nous recensions cinq comportements à
éviter :
- 1) Réinventer la roue
- 2) Oublier la convention de nommage
- 3) Ne pas commenter son code
- 4) Utiliser " printf " à toute occasion
- 5) Ne pas se limiter en variables temporaires
Nous rajoutons aujourd'hui cinq autres points clefs dont il faut
se soucier afin de garder son code Php le plus propre et efficace
possible.
Tutoriel mis à jour le 21/11/2001.
6) Négliger la sécurité
de son application
La sécurité est un vaste domaine et une affaire de
spécialiste. Etre exhaustif est donc hors de portée
de cet article. Rassurez-vous, tout n'est pas perdu pour autant.
En effet, entre tenter d'obtenir un système fiable à
100% et permettre à son site d'éviter certains écueils
connus, il y a une différence de taille. Nous évoquerons
ici quelques-uns de ces dangers, et les moyens de les éviter.
"Prévoir le pire", voilà en résumé
la conduite à adopter lors de la conception d'une application,
écrite en Php ou non d'ailleurs.
Bien sûr, le niveau de sécurité requis et les
conséquences d'un piratage ou d'une mauvaise action, parfois
involontaire de la part d'un internaute, n'ont pas les mêmes
conséquences sur un site de commerce électronique
ou sur un site personnel. Toutefois, optimiser le site dont on s'occupe,
personnel ou non, est une bonne chose.
Voyons où se situent certaines failles et comment y remédier.
Certaines étapes d'apparence anodine telle que l'inscription
d'un internaute sur votre site, peuvent pourtant apporter leur lot
de problèmes.
Si vous souhaitez par exemple recueillir l'adresse email d'un internaute
avant de le laisser s'inscrire sur votre site, il se peut que celui-ci
soit tenté de saisir une adresse invalide.
Que faire alors ? Vous pouvez toujours traiter la chaîne de
caractères reçue grâce aux expressions
régulières mais est-ce vraiment utile ? Au mieux
vous détecterez que la syntaxe de l'email n'est pas correcte
(pas de "@", pas de ".", etc) mais alors comment
réagir face à un email syntaxiquement valide tel que
:
toto@site-inconnu.com
Il reste à vérifier si le serveur existe
("socket validation"). Si celui-ci est temporairement
en panne, vous rejettez l'email, pas de chance pour l'internaute...
Un internaute de perdu, dix de retrouvés pensez-vous ? Sans
doute pas mais le problème n'est pas là. Il existe
un cas plus vicieux encore :
nom.connu@site-connu.com
Le site existe, le compte "nom.connu" aussi... Bien sûr,
ça n'est pas l'email de l'internaute, mais il est valide.
Non, la seule solution vraiment fiable est de rallonger le processus
d'inscription en obligeant l'internaute a cliquer sur un lien contenu
dans un email que vous lui avez préalablement envoyé.
Dans ce cas vous êtes sûr que celui-ci dispose d'un
email et que c'est le sien (passons sur la mailbox familiale ou
le compte piraté).
Rien ne vous dit par contre que ce n'est pas une de ces adresse
"gratuites" créee pour l'occasion, mais qu'importe,
vous avez votre email.
Convenons-en, ces problèmes d'emails ne mettent pas en péril
la sécurité de votre application. A la rigueur quelques
"mailer-daemon" vous reviennent après l'envoi de
votre newsletter, mais c'est tout.
Leur "intérêt" principal est en fait ailleurs
: vous mettre la puce à l'oreille quant à la fiabilité
du contenu renseigné par l'internaute.
Celui-ci peut en effet se revéler être plus dramatique
qu'un email invalide.
Lorsque vous récupérez une variable renseignée
par un internaute, vous pouvez utiliser la commande "escapeshellcmd"
afin "d'échapper" tous les caractères susceptibles
d'activer une commande Shell.
En d'autres termes cette commande place le caractère "\"
devant chaque caractère potentiellement "dangereux"
(#, &, ´, ', \, ", |, *, etc...). Ce caractère
n'est en effet pas ajouté automatiquement lorsque les chaînes
de caractères sont stockées par Php, cela dépend
notamment de l'utilisation de la variable "magic_quotes".
Un "phpinfo()" sur votre site vous indiquera si elle est
activée ou pas.
Attention : si le Php est capable de stocker certaines données
comprenant des caractères spéciaux, il n'en est pas
forcément de même pour la base de données. L'utilisation
de la fonction "addslahes"
peut alors aider.
Enfin, quelques règles simples sont à appliquer :
Ne pas transmettre de mot de passe en clair par URL ou
formulaire.
Ceci est aussi valable pour des prix, ou d'autres informations sensibles.
Afin de limiter les problèmes de piratage (soumission d'un
prix issu d'un autre domaine par exemple), stockez ce type d'informations
dans une base de données, effectuez les calculs du
côté serveur (JavaScript ne suffit pas) !
De même, si l'utilisation de Javascript est souhaitable à
des fins de vérification de formulaire (et éviter
ainsi à l'internaute d'attendre la réponse du serveur),
il faut systématiquement doubler tous les tests effectués
du côté client par des traitements au moins équivalents
du côté serveur. N'oubliez pas que JavaScript peut
se désactiver...
D'autres éléments à prendre en compte au niveau
sécurité se trouvent sur le
site officiel de Php. Un autre article très intéressant
est lui aussi à lire sur Phpbuilder.com.
7) "Copier / Coller" sans comprendre
A quoi bon s'appliquer à rendre son code Php le plus fiable
et le plus propre possible si c'est pour inclure du code que vous
ne maîtrisez pas dans votre application ?
Télécharger des scripts sur Internet doit d'abord
être un moyen de comprendre comment d'autres programmeurs
ont résolu votre problème. Une fois le travail de
compréhension effectué, les modifications éventuellement
apportées, alors seulement vous pouvez inclure le code (Open)
source dans le vôtre.
Méfiez-vous des bouts de script qu'on croise parfois dans
les forums de discussion, certains sont de vrais joyaux et sont
fiables, d'autres ne vous apporteront peut-être que des ennuis
!
Dans tous les cas il faut le comprendre, ne serait-ce que pour pouvoir
maintenir par la suite votre application.
Enfin, "patcher" son code sans réellement refondre
le script téléchargé dans son application casse
la logique qui était celle de votre script. Cela ralentit
votre application Php et la rend moins lisible. Qu'en est-il en
effet des conventions de nommage adoptées par l'auteur des
lignes de code que vous souhaitez réutiliser ? Si vous n'y
prenez garde vous risquez un conflit de variable qui risque de ne
pas être évident à détecter.
Bref, s'inspirer de la communauté et ne pas réinventer
la roue, oui, mais à condition de comprendre comment elle
tourne...
8) Ne pas gérer les erreurs éventuelles
Nous parlions tout à l'heure de sécurité,
voici un type d'erreur qui peut conduire à des problèmes
dans ce domaine.
Si l'erreur est parfois imprévisible, ne pensez pas qu'il
soit pour autant impossible de l'intercepter. S'il est en effet
difficile de prévoir tout ce qui peut se passer sur un site,
vous pouvez néanmoins vérifier que les résultats
que vous obtenez sont cohérents et correspondent à
vos attentes.
Si vous ne faites rien, vous exposez vos utilisateurs à
des messages d'erreurs déjà parfois difficilement
compréhensibles par un informaticien... De plus, ces erreurs
de script Php (parfois générés par la base
de données) peuvent renseigner un pirate éventuel.
Chaque bribe d'information récupérée peut constituer
un point de départ pour un pirate : un message de debug que
vous laissez affiché en cas de plantage, le type du SGBD,
mieux encore le nom d'une table ou de la base...
Aussi, ces messages ne doivent pas apparaître sans un contrôle
de votre part, c'est l'objectif de la gestion d'erreur ou "error
handling".
Vous pouvez alors profiter des possibilités offertes par
Php dans ce domaine (voir
notre tutoriel) et indiquer à Php de remonter le maximum
de "warning" possibles, un peu comme si vous descendiez
la tolérance d'un compilateur. Pour cela,
donnez la valeur "E_ALL" au "reporting level".
Afin de remonter le maximum d'erreurs, plusieurs éléments
sont à tester : les connections aux bases de données,
les valeurs retournées par les fonctions... Exemple :
$messerreur = "Veuillez nous excuser
pour cet incident.";
$req="select nom, prenom from membres where id = 2";
$idreq=mysql_query($req,$idconnect);
if ($idreq == 0)
{
print "Erreur selection nom,
prenom.<br>";
echo("$messerreur<br>");
mysql_close($idconnect);
exit;
}
Si votre requête est invalide, le script s'arrête ici
(afin d'éviter un plantage certain un peu plus loin) et affiche
un message d'erreur particulier "sélection nom, prénom"
avec en plus un message plus générique défini
dans une bibliothèque par exemple (ici $messerreur).
9) Ne pas faire relire son code
Sans pour autant adopter des méthodes dignes de "l'eXtreme
programming", faire relire votre code par un oeil extérieur
est une très bonne chose. Qui n'a jamais passé de
(trop) longues minutes, heures (?) autour de quelques lignes de
code qui ne fonctionnaient pas, pour s'apercevoir au final qu'il
ne s'agissait que d'une grossière erreur ?
Imaginez le temps gagné si vous aviez appelé un collègue
à la rescousse...
Faire relire son code par quelqu'un qui n'a pas été
impliqué dans son processus de production permet d'obtenir
une toute autre vue que la sienne sur l'ensemble de la chose.
Des bugs peuvent ainsi être décelés bien plus
rapidement que si c'est vous qui vous étiez relu. C'est aussi
l'occasion de revoir sa documentation si celle-ci est jugée
peu lisible.
10) Négliger les bases de données
Optimiser son code Php ne sert à rien si c'est pour saccager
la partie "bases de données". Deux erreurs à
éviter :
- La mauvaise utilisation de certaines fonctions d'accès
aux bases de données
- Reporter sur le Php des traitements dont SQL peut s'acquitter.
Lister toutes les mauvaises utilisations possibles des fonctions
Php dédiées aux bases de données n'a pas de
sens, alors un conseil : lorsque vous avez besoin d'une de ces fonctions,
choisissez celle qui parmi la
liste disponible (ici MySQL) est celle qui correspond le mieux
à votre cas. Inutile en effet de prendre un canon
pour tuer une mouche.
Par exemple, n'utilisez pas "mysql_fetch_row" pour tester
uniquement si votre requête a renvoyé des tuples mais
plutôt "mysql_nums_row" qui est conçu pour
cette tâche (si votre SGBD la supporte). Trouvez la fonction
minimale pour effectuer ce dont vous avez besoin.
Idem pour stocker les données issues d'une requête,
n'inventez pas de système complexe de votre cru alors que
"mysql_fetch_array" vous propose par exemple un tableau
associatif très pratique :
$req="select nom, prenom from membres
where id = 2";
$idreq=mysql_query($req,$idconnect);
// On passe sur les tests de validité de la requête
ici...
// La requête ne ramène qu'un seul tuple.
$row=mysql_fetch_array($idreq)
$nom_user = $row[nom];
$prenom_user = $row[prenom];
C'est lisible, court, que demander de plus ?
Passons au SQL... Maîtriser ce langage, tout du moins ses
bases, est très important. La rapidité de votre site
en dépend.
Véritable cauchemar des hébergeurs mutualisés,
la clause " SELECT * " appliquée sur une large
table est une aberration lorsque l'on souhaite ne récupérer
que quelques champs.
Rappatriez uniquement ce dont vous avez besoin !
Indiquez les champs, un par un, que vous souhaitez ramener.
Admettons que votre table "membres" ne comprenne que deux
champs aujourd'hui : Nom et prénom. Vous souhaitez récupérer
les deux champs. Un "SELECT * " ne fera effectivement
pas de dégât... pour cette fois-ci. Et si demain la
structure de votre table change pour s'enrichir d'une dizaine de
champ ?
Si vous ne modifiez pas votre SELECT, que vous auriez pu écrire
correctement dès le départ, ce sont dix champs de
trop que vous aller ramener...
De manière générale, le "SELECT * "
est à proscrire, c'est une bonne habitude à prendre
que de nommer, un par un, les champs dont vous avez besoin.
De même, utilisez la clause "WHERE" pour
réduire encore le nombre de tuples à rappatrier de
la base. Inutile de d'abord tout ramener et de faire le tri en Php,
par exemple dans la boucle "while" de l'exemple ci-dessus...
Utiliser des "if" pour identifier un enregistrement spécifique
n'a pas lieu d'être quand on peut le ramener, seul, grâce
à une clause WHERE.
Intéressez-vous à SQL si ça n'est pas encore
le cas, il existe plusieurs tutoriels sur le web dédié
à ce langage, en voici un où vous pouvez tester
vos requêtes.
Ainsi s'achève notre série d'erreurs à ne
pas commettre. Certains principes débordaient du seul langage
Php mais il était bon de les rappeler. Cette liste d'erreurs
n'est hélas pas exhaustive, il en existe d'autres, à
vous de vous poser les bonnes questions lors de la conception de
vos scripts futurs, discutez-en avec la communauté Php francophone,
qui par chance est très active, et échangez vos expériences,
c'est comme cela que l'on progresse le plus rapidement.
|