¿Por qué necesitamos la validación del lado del servidor?
- Su validación del lado del cliente no es suficiente y puede ser subvertida
- Más propenso a los ataques Man in middle, y el servidor nunca debería confiar en el lado del cliente
- Un usuario puede desactivar la validación de JavaScript del lado del cliente y manipular los datos
Si ha estado creando aplicaciones web utilizando un marco Express o cualquier otro marco Node.js, la validación juega un papel crucial en cualquier aplicación web que requiera que valide la solicitud body
param
query
.
Escribir su propia función de middleware puede resultar engorroso si
- desea moverse rápido mientras mantiene la calidad del código o
- desea evitar usar o en su función de controlador principal donde define la lógica de negocios
if (req.body.head)
if (req.params.isCool)
En este tutorial, aprenderá cómo validar la entrada en una aplicación Express.js utilizando un módulo popular y de código abierto llamado express-validator.
Introducción a express-validator
La definición en Github dice:
express-validator es un conjunto de middlewares express.js que envuelve las funciones de validación y desinfección de validator.js.El módulo implementa cinco API importantes:
- Ver API
- API de filtro
- API de cadena de desinfección
- API de cadena de validación
- API de resultados de validación
Echemos un vistazo a un usuario básico route
sin ningún módulo de validación para crear un usuario:/route/user.js
/** * @api {post} /api/user Create user * @apiName Create new user * @apiPermission admin * @apiGroup User * * @apiParam {String} [userName] username * @apiParam {String} [email] Email * @apiParam {String} [phone] Phone number * @apiParam {String} [status] Status * * @apiSuccess (200) {Object} mixed `User` object */ router.post('/', userController.createUser)
Ahora en controlador de usuario /controllers/user.js
const User = require('./models/user') exports.createUser = (req, res, next) => { /** Here you need to validate user input. Let's say only Name and email are required field */ const { userName, email, phone, status } = req.body if (userName && email && isValidEmail(email)) { // isValidEmail is some custom email function to validate email which you might need write on your own or use npm module User.create({ userName, email, phone, status, }) .then(user => res.json(user)) .catch(next) } }
El código anterior es solo un ejemplo básico de validación de campos por su cuenta.
Puede manejar algunas validaciones en su modelo de usuario usando Mongoose. Para las mejores prácticas, queremos asegurarnos de que la validación ocurra antes que la lógica empresarial.
express-validator se encargará de todas estas validaciones y también de la desinfección de las entradas.
Instalación
npm install --save express-validator
Incluya el módulo en su server.js
archivo principal :
const express = require('express') const bodyParser = require('body-parser') const expressValidator = require('express-validator') const app = express() const router = express.Router() app.use(bodyParser.json()) app.use(expressValidator()) app.use('/api', router)
Ahora usando express-validator, /routes/user.js
será así:
router.post( '/', userController.validate('createUser'), userController.createUser, )
Aquí userController.validate
hay una función de middleware que se explica a continuación. Acepta el method
nombre para el que se utilizará la validación.
Creemos una función de middleware validate()
en nuestro /controllers/user.js
:
const { body } = require('express-validator/check') exports.validate = (method) => { switch (method) { case 'createUser': { return [ body('userName', 'userName doesn't exists').exists(), body('email', 'Invalid email').exists().isEmail(), body('phone').optional().isInt(), body('status').optional().isIn(['enabled', 'disabled']) ] } } }
Consulte este artículo para obtener más información sobre la definición de funciones y su uso.
La body
función solo validará req.body
y toma dos argumentos. Primero es el property name
. En segundo lugar, está su costumbre message
que se mostrará si falla la validación. Si no proporciona un mensaje personalizado, se utilizará el mensaje predeterminado.
Como puede ver, para un required
campo estamos usando el .exists()
método. Estamos usando .optional()
para un optional
campo. De manera similar isEmail()
isInt()
se usa para validar email
y integer
.
Si desea que un campo de entrada incluya solo ciertos valores, puede usar .isIn([])
. Esto toma un array
valor de, y si recibe valores distintos a los anteriores, se generará un error.
Por ejemplo, el campo de estado en el fragmento de código anterior solo puede tener un valor enabled
o disabled
. Si proporciona cualquier valor que no sea ese, se producirá un error.
En /controllers/user.js
, escriba una createUser
función en la que pueda escribir lógica empresarial. Se llamará despuésvalidate()
con el resultado de las validaciones.
const { validationResult } = require('express-validator/check'); exports.createUser = async (req, res, next) => { try { const errors = validationResult(req); // Finds the validation errors in this request and wraps them in an object with handy functions if (!errors.isEmpty()) { res.status(422).json({ errors: errors.array() }); return; } const { userName, email, phone, status } = req.body const user = await User.create({ userName, email, phone, status, }) res.json(user) } catch(err) { return next(err) } }
Si se pregunta qué es validationResult (req)?
Esta función encuentra los errores de validación en esta solicitud y los envuelve en un objeto con funciones útiles
Ahora, siempre que la solicitud incluya parámetros de cuerpo no válidos o userName
falte un campo req.body
, su servidor responderá así:
{ "errors": [{ "location": "body", "msg": "userName is required", "param": "userName" }] }
Entonces, si userName
o email
no logró satisfacer la validación, cada error devuelto por el .array()
método tiene el siguiente formato por defecto:
{ "msg": "The error message", "param": "param name", "value": "param value", // Location of the param that generated this error. // It's either body, query, params, cookies or headers. "location": "body", // nestedErrors only exist when using the oneOf function "nestedErrors": [{ ... }] }
Como puede ver, este módulo realmente nos ayuda a encargarnos de la mayoría de las validaciones por sí solo. También mantiene la calidad del código y se centra principalmente en la lógica empresarial.
Esta fue la introducción a la validación de entrada usando el módulo express-validator y vea cómo validar una matriz del artículo y hacer su propia validación personalizada en la Parte 2 de esta serie.
He hecho todo lo posible y espero haber cubierto lo suficiente para explicarlo en detalle para que pueda comenzar.
Si tiene algún problema, no dude en ponerse en contacto o comentar a continuación.
Me gustaría ayudar :)
Sigue a Shailesh Shekhawat para recibir notificaciones cada vez que publique una nueva publicación.
¡No dudes en aplaudir si consideras que es una lectura que vale la pena!
Publicado originalmente en 101node.io el 2 de septiembre de 2018.