Je souhaite obtenir des informations sur une formation complète concernant le thème DIVI dispensé
par un organisme de formation certifié par l’état.
Que la formation soit finançable par mon CPF (idéalement) ou autre


Lors de la création d’une application Web, vous devrez probablement créer des formulaires HTML le premier jour. Ils font partie intégrante de l’expérience Web et peuvent être compliqués.

En règle générale, le processus de traitement des formulaires comprend:

  • Afficher un formulaire HTML vierge en réponse à une lettrine GET enquête
  • Utilisateur qui a rempli le formulaire avec des données dans un POST enquête
  • Validation à la fois sur le client et sur le serveur
  • réafficher le formulaire avec les données d’échappement et les messages d’erreur s’il n’est pas valide
  • à faire quelque chose avec les données nettoyées sur le serveur si tout est valide
  • Transférer l’utilisateur ou afficher un message de réussite après le traitement.

Le traitement des données de formulaire est associé à des aspects de sécurité supplémentaires.

Nous allons passer en revue tout cela et expliquer comment les créer avec Node.js et Express – le framework Web le plus populaire pour Node. Tout d’abord, nous allons créer un formulaire de contact simple qui permet aux utilisateurs d’envoyer en toute sécurité un message et une adresse e-mail, puis examiner ce qui est requis lors du traitement des téléchargements de fichiers.

Un formulaire de contact avec email et message avec des erreurs de validation

Comme toujours, le code complet se trouve dans notre Dépôt GitHub.

À installer

Assurez-vous que la dernière version de Node.js est installée. node -v devrait revenir 8.9.0 ou plus.

Téléchargez le code de démarrage avec Git ici:

git clone -b starter https://github.com/sitepoint-editors/node-forms.git node-forms-starter
cd node-forms-starter
npm install
npm start

Remarque: le repo a deux branches: starter et master. le starter La branche contient la configuration minimale dont vous avez besoin pour suivre cet article. le master Branch contient une démo complète et fonctionnelle (lien ci-dessus).

Qui n’existe pas trop Code là-dedans. C’est juste d’avoir une configuration express à nu Modèles EJS et routines de gestion des erreurs:


const path = require('path');
const express = require('express');
const layout = require('express-layout');

const routes = require('./routes');
const app = express();

app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

const middlewares = [
  layout(),
  express.static(path.join(__dirname, 'public')),
];
app.use(middlewares);

app.use("https://www.sitepoint.com/", routes);

app.use((req, res, next) => {
  res.status(404).send("Sorry can't find that!");
});

app.use((err, req, res, next) => {
  console.error(err.stack);
  res.status(500).send('Something broke!');
});

app.listen(3000, () => {
  console.log('App running at http://localhost:3000');
});

L’URL racine / rend juste le index.ejs Vue:


const express = require('express');
const router = express.Router();

router.get("https://www.sitepoint.com/", (req, res) => {
  res.render('index');
});

module.exports = router;

Voir le formulaire

Lorsque les gens font une demande GET à /contactnous voulons rendre une nouvelle vue contact.ejs::


router.get('/contact', (req, res) => {
  res.render('contact');
});

Vous pouvez utiliser le formulaire de contact pour nous envoyer un message et votre adresse email:


<div class="form-header">
  <h2>Send us a message</h2>
</div>
<form method="post" action="/contact" novalidate>
  <div class="form-field">
    <label for="message">Message</label>
    <textarea class="input" id="message" name="message" rows="4" autofocus></textarea>
  </div>
  <div class="form-field">
    <label for="email">Email</label>
    <input class="input" id="email" name="email" type="email" value="" />
  </div>
  <div class="form-actions">
    <button class="btn" type="submit">Send</button>
  </div>
</form>

Voyez à quoi ça ressemble http://localhost:3000/contact.

Soumettre le formulaire

Pour obtenir les valeurs POST dans Express, vous devez d’abord les inclure body-parser Middleware qui affiche les valeurs de formulaire soumises req.body dans vos guides d’itinéraire. Ajoutez-le à la fin du middlewares Déployer:


const bodyParser = require('body-parser');

const middlewares = [
  
  bodyParser.urlencoded({ extended: true }),
];

Il s’agit d’une convention courante pour les formulaires de renvoyer des données à la même URL que celle utilisée dans la première requête GET. Faisons cela ici et gérons POST /contact pour traiter l’entrée utilisateur.

Regardons d’abord la soumission invalide. Si cela n’est pas valide, nous devons renvoyer les valeurs soumises à la vue avec tous les messages d’erreur que nous voulons afficher (afin que les utilisateurs n’aient pas à les saisir à nouveau):

router.get('/contact', (req, res) => {
  res.render('contact', {
    data: {},
    errors: {}
  });
});

router.post('/contact', (req, res) => {
  res.render('contact', {
    data: req.body, 
    errors: {
      message: {
        msg: 'A message is required'
      },
      email: {
        msg: 'That email doesn‘t look right'
      }
    }
  });
});

S’il y a des erreurs de validation, nous procédons comme suit:

  • Afficher les erreurs en haut du formulaire
  • Définissez les valeurs d’entrée sur ce qui a été envoyé au serveur
  • Afficher les erreurs en ligne sous les entrées
  • ajouter un form-field-invalid Idéal pour les champs avec des erreurs.

<div class="form-header">
  <% if (Object.keys(errors).length === 0) { %>
    <h2>Send us a message</h2>
  <% } else { %>
    <h2 class="errors-heading">Oops, please correct the following:</h2>
    <ul class="errors-list">
      <% Object.values(errors).forEach(error => { %>
        <li><%= error.msg %></li>
      <% }) %>
    </ul>
  <% } %>
</div>

<form method="post" action="/contact" novalidate>
  <div class="form-field <%= errors.message ? 'form-field-invalid' : '' %>">
    <label for="message">Message</label>
    <textarea class="input" id="message" name="message" rows="4" autofocus><%= data.message %></textarea>
    <% if (errors.message) { %>
      <div class="error"><%= errors.message.msg %></div>
    <% } %>
  </div>
  <div class="form-field <%= errors.email ? 'form-field-invalid' : '' %>">
    <label for="email">Email</label>
    <input class="input" id="email" name="email" type="email" value="<%= data.email %>" />
    <% if (errors.email) { %>
      <div class="error"><%= errors.email.msg %></div>
    <% } %>
  </div>
  <div class="form-actions">
    <button class="btn" type="submit">Send</button>
  </div>
</form>

Envoyez le formulaire à http://localhost:3000/contact pour voir cela en action. C’est tout ce dont nous avons besoin du côté de la vue.

Validation et désinfection

Il existe un middleware pratique appelé Validateur express pour la validation et la désinfection des données avec le validator.js Une bibliothèque. Ajoutons-le à notre application.

Validation

Avec le Validateurs à condition que nous puissions vérifier facilement qu’un message et une adresse e-mail valide ont été fournis:


const { check, validationResult, matchedData } = require('express-validator');

router.post('/contact', [
  check('message')
    .isLength({ min: 1 })
    .withMessage('Message is required'),
  check('email')
    .isEmail()
    .withMessage('That email doesn‘t look right')
], (req, res) => {
  const errors = validationResult(req);
  res.render('contact', {
    data: req.body,
    errors: errors.mapped()
  });
});

désinfection

Avec le Désinfectants En supposant que nous pouvons tronquer les espaces du début et de la fin des valeurs et normaliser l’adresse e-mail dans un modèle cohérent. Cela peut aider à supprimer les contacts en double créés en entrant légèrement différemment. Par exemple, ' [email protected]' et '[email protected] ' seraient tous les deux réaménagés '[email protected]'.

Les désinfectants peuvent simplement être enchaînés à l’extrémité des validateurs:


router.post('/contact', [
  check('message')
    .isLength({ min: 1 })
    .withMessage('Message is required')
    .trim(),
  check('email')
    .isEmail()
    .withMessage('That email doesn‘t look right')
    .bail()
    .trim()
    .normalizeEmail()
], (req, res) => {
  const errors = validationResult(req);
  res.render('contact', {
    data: req.body,
    errors: errors.mapped()
  });

  const data = matchedData(req);
  console.log('Sanitized:', data);
});

le matchedData La fonction renvoie la sortie de désinfectant pour notre entrée.

Notez également notre utilisation du verser Méthode qui arrête d’exécuter les validations si l’une des précédentes a échoué. Nous en avons besoin car si un utilisateur soumet le formulaire sans entrer de valeur dans le champ e-mail, le normalizeEmail essaiera de normaliser une chaîne vide et de la convertir en une @. Cela sera ensuite ajouté à notre boîte e-mail lorsque nous rendrons le formulaire.

Le formulaire valide

S’il y a des erreurs, nous devons rendre à nouveau la vue. Sinon, nous devons faire quelque chose d’utile avec les données et montrer ensuite que le transfert a réussi. En règle générale, la personne est redirigée vers une page de réussite et un message s’affiche.

HTTP est sans état, vous ne pouvez donc pas rediriger vers une autre page et Passer des messages sans l’aide d’un Cookie de session pour conserver ce message entre les requêtes HTTP. Un « message flash » est le nom de ce type de message à usage unique que nous souhaitons conserver via une redirection, puis le faire disparaître.

Il y a trois middlewares que nous devons inclure afin de câbler cela:


const cookieParser = require('cookie-parser');
const session = require('express-session');
const flash = require('express-flash');

const middlewares = [
  
  cookieParser(),
  session({
    secret: 'super-secret-key',
    key: 'super-secret-cookie',
    resave: false,
    saveUninitialized: false,
    cookie: { maxAge: 60000 }
  }),
  flash(),
];

le express-flash Le middleware ajoute req.flash(type, message)que nous pouvons utiliser dans nos gestionnaires de route:


router.post('/contact', [
  
], (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.render('contact', {
      data: req.body,
      errors: errors.mapped()
    });
  }

  const data = matchedData(req);
  console.log('Sanitized: ', data);
  

  req.flash('success', 'Thanks for the message! I‘ll be in touch :)');
  res.redirect("https://www.sitepoint.com/");
});

le express-flash Le middleware ajoute messages à req.locals auquel toutes les vues ont accès:


<% if (messages.success) { %>
  <div class="flash flash-success"><%= messages.success %></div>
<% } %>

<h1>Working With Forms in Node.js</h1>

Vous devriez maintenant être redirigé vers index Afficher et afficher un message de réussite lorsque le formulaire est soumis avec des données valides. Huzzah! Nous pouvons maintenant l’utiliser pour la production et recevoir des nouvelles du prince du Nigéria.

Envoyer un e-mail avec un nœud

Vous avez peut-être remarqué que l’envoi du courrier électronique est laissé au lecteur comme devoir. Ce n’est pas aussi difficile qu’il y paraît et peut être réalisé avec le Paquet Nodemailer. Tu peux trouver Les instructions de configuration peuvent être trouvées ici, ou un tutoriel plus détaillé ici.

Considérations de sécurité

Lorsque vous travaillez avec des formulaires et des sessions sur Internet, vous devez être conscient des vulnérabilités de sécurité générales dans les applications Web. Le meilleur avis de sécurité que j’ai reçu est: « Ne faites jamais confiance au client! »

TLS sur HTTPS

Utilisez toujours le cryptage TLS terminé https:// Si vous travaillez avec des formulaires pour que les données soumises soient cryptées lors de leur envoi sur Internet. Lors de la soumission des données du formulaire http://Il est envoyé en clair et peut être vu par toute personne écoutant ces paquets lors de son voyage sur le Web.

Si vous souhaitez en savoir plus sur l’utilisation de SSL / TLS dans Node.js, veuillez contacter Ce post.

Portez votre casque

Il y a un joli petit middleware appelé casque Cela augmente la sécurité des en-têtes HTTP. Il est préférable d’être au sommet de votre middleware, et il est très facile d’inclure:


const helmet = require('helmet');

middlewares = [
  helmet(),
  
];

Falsification de requêtes intersites (CSRF)

Vous pouvez vous en protéger Falsification des demandes de renseignements croisés en générant un jeton unique lorsqu’un formulaire est présenté à l’utilisateur, puis en validant ce jeton avant de traiter les données POST. Il y a un Intergiciel pour vous aider ici aussi:


const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });

Dans la requête GET, nous générons un jeton:


router.get('/contact', csrfProtection, (req, res) => {
  res.render('contact', {
    data: {},
    errors: {},
    csrfToken: req.csrfToken()
  });
});

Et aussi dans la réponse aux erreurs de validation:

router.post('/contact', csrfProtection, [
  
], (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.render('contact', {
      data: req.body,
      errors: errors.mapped(),
      csrfToken: req.csrfToken()
    });
  }

  
});

Ensuite, il suffit d’inclure le jeton dans une entrée masquée:


<form method="post" action="/contact" novalidate>
  <input type="hidden" name="_csrf" value="<%= csrfToken %>">
  
</form>

C’est tout ce qu’il faut.

Nous n’avons pas besoin de modifier notre gestionnaire de requêtes POST car toutes les requêtes POST nécessitent désormais un jeton valide du csurf Middleware. Si un jeton CSRF valide n’est pas fourni, un ForbiddenError Une erreur est sortie qui peut être gérée par le gestionnaire d’erreurs défini à la fin de server.js.

Vous pouvez le tester vous-même en modifiant le jeton à l’aide des outils de développement de votre navigateur ou en le supprimant du formulaire et en le soumettant.

Scripts intersites (XSS)

Vous devez être prudent lorsque vous affichez les données soumises par l’utilisateur dans une vue HTML, car cela peut vous ouvrir Scripts intersites (XSS). Tous les langages de modèle offrent différentes méthodes pour générer des valeurs. L’EJS <%= value %> sort le HTML échappé Cela vaut la peine de vous protéger du XSS tout en <%- value %> renvoie une chaîne brute.

Toujours utiliser la sortie masquée <%= value %> lorsqu’il s’agit de valeurs soumises par l’utilisateur. N’utilisez les dépenses brutes que si vous êtes certain que vous pouvez le faire en toute sécurité.

Téléchargements de fichiers

Le téléchargement de fichiers dans des formulaires HTML est un cas particulier qui nécessite un type d’encodage "multipart/form-data". Voir Guide MDN pour la soumission de données de formulaire En savoir plus sur ce qu’il advient des soumissions de formulaires en plusieurs parties.

Vous avez besoin d’un middleware supplémentaire pour gérer les téléchargements en plusieurs parties. Il y a un colis express avec le nom Multer nous allons utiliser ceci ici:


const multer = require('multer');
const upload = multer({ storage: multer.memoryStorage() });

router.post('/contact', upload.single('photo'), csrfProtection, [
  
], (req, res) => {
  

  if (req.file) {
    console.log('Uploaded: ', req.file);
    
  }

  req.flash('success', 'Thanks for the message! I’ll be in touch :)');
  res.redirect("https://www.sitepoint.com/");
});

Ce code indique multer pour télécharger le fichier dans le champ « Photo » en mémoire et enregistrer le fichier File Objet dans req.fileque nous pouvons inspecter ou traiter.

La dernière chose dont nous avons besoin est d’ajouter le enctype Attribut et notre entrée de fichier:

<form method="post" action="/contact?_csrf=<%= csrfToken %>" novalidate enctype="multipart/form-data">
  <input type="hidden" name="_csrf" value="<%= csrfToken %>">
  <div class="form-field <%= errors.message ? 'form-field-invalid' : '' %>">
    <label for="message">Message</label>
    <textarea class="input" id="message" name="message" rows="4" autofocus><%= data.message %></textarea>
    <% if (errors.message) { %>
      <div class="error"><%= errors.message.msg %></div>
    <% } %>
  </div>
  <div class="form-field <%= errors.email ? 'form-field-invalid' : '' %>">
    <label for="email">Email</label>
    <input class="input" id="email" name="email" type="email" value="<%= data.email %>" />
    <% if (errors.email) { %>
      <div class="error"><%= errors.email.msg %></div>
    <% } %>
  </div>
  <div class="form-field">
    <label for="photo">Photo</label>
    <input class="input" id="photo" name="photo" type="file" />
  </div>
  <div class="form-actions">
    <button class="btn" type="submit">Send</button>
  </div>
</form>

Essayez de télécharger un fichier. Tu devrais voir ça File objets enregistrés dans la console.

Remplir les entrées de fichier

En cas d’erreurs de validation, nous ne pouvons pas remplir les entrées de fichier comme nous l’avons fait pour les entrées de texte (C’est un risque de sécurité). Une approche courante pour résoudre ce problème implique les étapes suivantes:

  • Téléchargez le fichier vers un emplacement temporaire sur le serveur
  • Affiche une vignette et un nom de fichier du fichier joint
  • Ajout de JavaScript au formulaire afin que les utilisateurs puissent supprimer le fichier sélectionné ou en télécharger un nouveau
  • Déplacez le fichier vers un emplacement permanent si tout est valide.

Souvent, en raison de la complexité accrue du travail avec les téléchargements en plusieurs parties et les fichiers, ils sont conservés dans des formulaires séparés.

Télécharger des fichiers avec des nœuds

Finalement, vous constaterez qu’il a été laissé au lecteur de mettre en œuvre la fonctionnalité de téléchargement réelle. Ce n’est pas aussi difficile qu’il y paraît et peut être réalisé avec différents packages tels que: Impressionant, ou Téléchargement rapide de fichiers. Tu peux trouver Les instructions de configuration peuvent être trouvées ici, ou un tutoriel plus détaillé ici.

Merci pour la lecture

J’espère que vous avez aimé vous familiariser avec les formulaires HTML et leur fonctionnement dans Express et Node.js. Voici un bref récapitulatif de ce que nous avons couvert:

  • Afficher un formulaire vierge en réponse à une demande GET
  • Traitement des données POST transmises
  • Afficher une liste d’erreurs, d’erreurs en ligne et de données soumises
  • Vérification des données transmises avec des validateurs
  • Nettoyez les données soumises avec des désinfectants
  • Transférer les messages en les transférant avec un message Flash
  • Protégez-vous des attaques telles que CSRF et XSS
  • Traitez les téléchargements de fichiers dans les soumissions de formulaires en plusieurs parties.

Dites-moi comment vous allez via Twitter!





Source link

Recent Posts