Alors que de nombreux guides de création de formulaires pour le Web se concentrent principalement sur le frontend, la sécurité va au-delà. Nous devons tenir compte de l’utilisateur actuel, des autres utilisateurs et de notre propre sécurité. En tant que tel, nous examinerons l’ensemble de l’architecture de l’application, du frontend au backend et au-delà.
Chiffrer le trafic (SSL)
Avant d’aller trop loin, j’utiliserai le terme « SSL » pour désigner une technologie utilisée pour crypter le trafic sur Internet. Techniquement, je veux dire Transport Layer Security (TLS), mais « SSL » est couramment utilisé et compris comme signifiant la même chose. C’est ce qui donne aux sites Web le petit verrou vert dans la barre d’URL et pourquoi ils commencent par « https » au lieu de » http » (pas de » s « ).
L’installation d’un certificat SSL est une bonne pratique pour plusieurs raisons, la sécurité étant la plus importante. Avoir un certificat SSL vous permet de crypter les données transmises entre le client (votre utilisateur) et le serveur (vous).
Un pirate informatique espionnant un réseau peut inspecter les paquets de données qu’un utilisateur envoie. Sans certificat SSL, ces données peuvent être facilement lues en texte brut. Avec un certificat SSL, les données peuvent toujours être interceptées, mais elles seraient envoyées sous forme de texte crypté, ce qui est à peu près inutile.
- Sans certificat SSL : nom d’utilisateur :
NuggetTheMighty; password: ILoveSquirrels
- Avec un certificat SSL (crypté) :
SIUFJaYQNtsn+y73mfBYv3fVfjJ2GdHl4A7XnTJXxgUyd4/TrU3nN+g3aJ4BVXSJL/E7
Ceci est particulièrement important lors de la création de formulaires, car le but d’un formulaire est d’envoyer des données. Nous devons à nos utilisateurs de protéger leurs données.
Obtenir et installer un certificat SSL coûtait du temps, de l’argent et un certain savoir-faire technique. Aujourd’hui, de nombreux services d’hébergement vous fourniront et installeront un certificat gratuitement. Dans de nombreux cas, ils le font même automatiquement.
Si votre service d’hébergement ne fournit pas de certificats SSL, il existe d’autres options :
- Cloudflare fournit un SSL « flexible » via leur DNS. C’est gratuit et facile, mais c’est probablement mieux d’avoir le vôtre.
- Si votre site utilise WordPress, il existe quelques plugins qui mettront en place un certificat en moins d’une minute, via Let’s Encrypt.
- Vous pouvez utiliser Certbot pour générer et installer un certificat pour vous via Let’s Encrypt.
Si vous n’avez toujours pas de certificat SSL parce que votre hébergeur n’en fournit pas et que vous n’avez pas le contrôle du DNS ou du code du serveur… eh bien, vous n’avez pas de chance. Vous allez devoir changer d’hôte, ou parler à votre administrateur de serveur, ou faire quelque chose car cela devrait être une exigence difficile pour tout projet de nos jours.
Comprendre GET vs POST
Dans un article précédent, j’ai dit que vous devriez toujours inclure le method
attribut sur vos formulaires. Les method
L’attribut indique au formulaire de soumettre des données avec le GET
ou POST
En-tête HTTP sur la requête. Si vous omettez le method
, le navigateur utilisera par défaut le GET
méthode. Ceci est important car il existe des différences significatives entre GET
et POST
demandes.
OBTENIR la demande
Jetez un œil au formulaire suivant en utilisant une méthode GET. Lorsque vous soumettez le formulaire, les données seront soumises à example.com (alerte spoiler, cela ne fait rien en fait).
L’élément clé à remarquer est l’URL après avoir soumis le formulaire. Bien que la forme action
est « exemple.com », l’URL de soumission est « exemple.com ?des-données-douces=blablablabla ». Ces paramètres de requête correspondent aux attributs de nom des entrées de formulaire. C’est ainsi que les formulaires utilisant le GET
données de transfert de méthode; paramètres de chaîne de requête.
La transmission de données en tant que paramètre d’URL est importante pour la sécurité pour plusieurs raisons :
- Pour de nombreux utilisateurs, les URL sont enregistrées dans l’historique du navigateur. Considérez si le formulaire envoyait un numéro de carte de crédit par paramètre de requête et que l’utilisateur se trouvait sur un ordinateur public, comme dans une bibliothèque. Leurs données privées pourraient se retrouver dans l’historique du navigateur pour que le prochain utilisateur puisse les voir.
- De nombreux serveurs conservent des journaux des URL qui ont reçu du trafic. Si des informations sensibles se retrouvent dans les fichiers journaux du serveur, toute personne ayant accès à ces fichiers peut voir les données.
Demande POST
Heureusement, vous pouvez utiliser le POST
méthode pour envoyer des données sans utiliser de paramètres de requête. Regardons le même formulaire, mais en utilisant le POST
méthode:
Remarquez comment la soumission de ce formulaire charge également example.com, mais cette fois il n’y a rien dans les paramètres de requête. C’est parce que sur un POST
demande, les données sont envoyées dans le corps de la demande. Cela rend plus difficile la fuite accidentelle d’informations privées.
En règle générale, j’utilise le POST
méthode sur tous les formulaires pour les raisons énumérées ci-dessus. Les quelques exceptions à cette règle sont si je veux laisser les utilisateurs mettre en signet leur soumission de formulaire ou la partager avec quelqu’un d’autre. Par exemple, consultez ce formulaire qui soumet la recherche à DuckDuckGo :
Une fois le formulaire soumis, DuckDuckGo s’ouvrira avec un paramètre de requête dans l’URL. Ensuite, vous pouvez, si vous le souhaitez, copier cette URL et la partager avec un collègue, ou la mettre en signet pour plus tard. Ce modèle peut être très utile à garder à l’esprit, sauf si vous traitez des données sensibles.
Eviter les SPAM
Personne n’aime les spams. Et j’admets que ce n’est que marginalement lié à la sécurité. Cela vaut la peine de le mentionner ici, car chaque fois que nous ajoutons un formulaire à une page Web publique, nous ouvrons la porte au spam. Les formulaires sont censés être remplis, mais parfois ils sont remplis par quelqu’un, ouchose, pour des raisons infâmes.
Alors comment l’empêcher?
Pots de miel
Un moyen rudimentaire de prévenir le spam s’appelle un « pot de miel » et le concept est assez simple. Si vous incluez une entrée cachée dans votre formulaire, vous savez qu’un vrai humain ne devrait jamais modifier ce champ. Par conséquent, si le formulaire est soumis avec des données pour cette entrée, vous pouvez supposer qu’il s’agissait d’un bot et rejeter la soumission.
En pratique, voici à quoi pourrait ressembler cette entrée :
<input name="honeypot" class="visually-hidden" tabindex="-1" autocomplete="off">
- Les
name
est important pour que vous sachiez quoi vérifier sur le backend. J’ai utilisé « pot de miel », mais la plupart des gens recommandent de l’appeler quelque chose qui semble plus légitime. - j’ai utilisé un
visually-hidden
classe pour masquer l’entrée des utilisateurs. Les bots le verront toujours. - Les
tabindex="-1"
supprime l’entrée de la navigation au clavier. Ceci est important pour les utilisateurs de technologies d’assistance. - Enfin, nous voulons empêcher le formulaire du navigateur de remplir automatiquement la saisie, nous désactivons donc
autocomplete
.
La bonne nouvelle à propos de cette approche est qu’elle peut coûter très peu de temps et d’efforts à mettre en œuvre. La mauvaise nouvelle est que de nombreux bots sont assez intelligents pour dire quand une entrée est un pot de miel et qu’ils l’ignoreront. Mais bon, même si cela arrête 10 pour cent du spam, le niveau d’effort en vaut la peine.
Défi de sécurité
Un moyen plus robuste de prévenir le spam consiste à inclure un défi que les utilisateurs doivent relever pour prouver qu’ils sont humains. Certains exemples de base sont des entrées qui vous demandent de répondre à une question mathématique simple comme « Qu’est-ce que 10 + 6 ? ». Seules les données avec la bonne réponse seront acceptées.
Le problème avec cette méthode est que, encore une fois, les bots peuvent être suffisamment sophistiqués pour résoudre ces problèmes.
Le dilemme du spam est un jeu du chat et de la souris en constante évolution qui a vu les défis devenir plus complexes au fil du temps. D’abord des questions mathématiques, puis la détection de lettres ou de chiffres dans les images.
Le défi de sécurité le plus connu est probablement reCAPTCHA. C’est un service maintenant détenu par Google qui montre aux utilisateurs un tas d’images qu’ils doivent identifier. Cela fonctionne très bien, et c’est gratuit. Si vous êtes préoccupé par la confidentialité des utilisateurs, vous ne voudrez peut-être pas utiliser les produits Google. La bonne nouvelle est qu’il existe un autre service appelé hCaptcha qui est un remplacement instantané. La technique du challenge de sécurité n’est pas sans inconvénients :
- Ils sont plus techniques à mettre en œuvre.
- Vous devrez peut-être faire appel à un service tiers.
- Ils peuvent avoir un impact négatif sur l’expérience utilisateur.
WAF et API
Si le spam devient un problème majeur dans vos formulaires, vous pouvez envisager de faire appel à un service tiers.
Une option consiste à configurer un pare-feu d’application Web (WAF). Un WAF se trouve devant votre serveur et empêche le trafic des mauvais acteurs d’accéder à votre site Web en premier lieu.
Cloudflare fonctionne au niveau DNS et propose un niveau gratuit très généreux. Je l’utilise sur tous les domaines que je possède et jusqu’à présent, je n’ai eu aucun problème de spam.
Une autre option consiste à utiliser un service API pour tester les soumissions de formulaires entrants. Le plus courant que je connaisse est Akismet qui fait partie des produits Automattic (ils fabriquent WordPress). Je l’ai utilisé sur certains sites WordPress et je peux dire que cela fonctionne bien. Ils ont également une API si vous n’utilisez pas WordPress. CSS Tricks a un article qui approfondit les API de spam tierces si vous êtes intéressé par d’autres options.
Je ne ferais confiance à aucune technique de prévention du spam pour être garantie à 100%. Le domaine est en constante évolution, les spammeurs devenant de plus en plus avancés chaque année. Cependant, ce n’est pas non plus le genre de problème que j’essaierais de résoudre jusqu’à ce que je l’aie. Dans ce cas, vous pouvez commencer avec quelques-uns des fruits à portée de main et progresser vers une solution plus complexe.
Compte tenu du niveau d’effort, de l’expérience utilisateur, du coût et de tout le reste, j’aborderais les choses comme ceci :
- Configurez Cloudflare sur votre DNS (ou un autre WAF)
- Utiliser des pots de miel
- Intégrer une API de détection de spam
- Configurer hCaptcha (dernier recours en raison de l’expérience utilisateur)
Valider les données
La validation est lorsque vous assurez que les données que vous recevez correspondent à ce que vous attendez. Par exemple, si j’enregistre un nouvel utilisateur, je veux m’assurer que l’e-mail qu’il fournit est bien une adresse e-mail.
Il y a généralement deux endroits où vous validez les données : côté client et côté serveur.
Validation côté client
La validation sur le front-end est généralement effectuée avec des attributs HTML ou avec JavaScript.
Par exemple, si nous voulions une entrée qui doit être remplie sous forme d’e-mail d’une longueur maximale, nous pourrions l’implémenter comme suit :
Si un utilisateur essaie de soumettre le formulaire sans répondre à nos exigences, le navigateur l’empêchera et affichera un message d’erreur à l’utilisateur.
Si nous ne voulons pas afficher l’interface utilisateur de validation intégrée, nous pouvons ajouter le novalidate
attribuer à notre forme. Cela empêchera la logique de validation par défaut et nous pourrons la remplacer par la nôtre.
Une approche consiste à utiliser le formulaire checkValidity
méthode pour voir si le formulaire a des entrées invalides. Si le formulaire n’est pas valide, nous pourrions parcourir chaque entrée et voir exactement quelle règle est enfreinte avec l’API ValidityState :
const form = document.querySelector('form');
form.addEventListener('submit', (event) => {
const isValid = form.checkValidity()
if (!isValid) {
const inputs = form.querySelectorAll('input')
for (const input of inputs) {
// Do some validation logic with the input
console.log(input.validity)
}
}
})
ValidityState
est très pratique car il nous donnera un objet où chaque paire clé/valeur représente un attribut de validation et son statut de validité :
{
badInput: Boolean
customError: Boolean
patternMismatch: Boolean
rangeOverflow: Boolean
rangeUnderflow: Boolean
stepMismatch: Boolean
tooLong: Boolean
tooShort: Boolean
typeMismatch: Boolean
valid: Boolean
valueMissing: Boolean
}
Cela peut nous mener assez loin. Nous pourrions afficher des messages d’erreur spécifiques pour chaque propriété invalide, ou modifier les noms de classe sur l’entrée (en fait, c’est ainsi que Vuetensils effectue la validation).
Je ne peux pas faire d’hypothèses sur votre implémentation, vous devrez donc partir d’ici. Si vous avez besoin de quelque chose de plus robuste, vous pouvez utiliser l’une des nombreuses bibliothèques de validation JavaScript sur NPM.
Qu’il s’agisse de votre propre implémentation ou d’une bibliothèque tierce, le côté client souffre d’un problème majeur…