¿Cómo iniciar sesión con una contraseña sin procesar cuando el almacenamiento de contraseñas en la base de datos tiene un formato hash en Node.js?

La contraseña almacenada en la base de datos siempre está en formato (hash+sal) por razones de seguridad. Cuando los usuarios se registran en cualquier sitio web, se proporciona una contraseña sin formato. Pero almacenar directamente las contraseñas sin procesar en la base de datos no es una buena práctica. Usando alguna lógica del lado del servidor, primero convertimos las contraseñas sin procesar en el formulario (hash + sal) y luego las almacenamos en la base de datos. Esto plantea un nuevo desafío, cómo comparar la contraseña sin formato proporcionada por el usuario en el momento del inicio de sesión y dar acceso al usuario sobre la base de si la contraseña es correcta o no.
 

Contraseña almacenada en la base de datos de la siguiente forma: 

Hashed(password, salt) 

Ejemplo: 
 

22cbca6aa74d3546971ca355a7641649b222a7858f97952f50d68ea65b3c5067a008ea4cdc8974461090a36d7815215 
ab4659d2333a94b15d43c758f4d08ab86dde4791

Pasos para configurar la lógica para iniciar sesión con contraseña sin formato: 

  • Busque en la base de datos con la ayuda de un nombre de usuario único o correo electrónico proporcionado por el usuario para iniciar sesión.
  • Busque el registro único y, si no lo encuentra, devuelva ‘Usuario no existe’.
  • Dividir la contraseña cifrada en ‘ . ‘ para encontrar la contraseña hash y la sal individualmente.
  • Codificó la contraseña sin procesar proporcionada por el usuario para iniciar sesión con el método ‘scrypt’ de Node.js usando sal.
  • Compare el hash obtenido con el hash obtenido al dividir la contraseña de la base de datos.
  • Si ambos hash son iguales, inicie sesión en el usuario y otorgue el acceso.
  • Si ambos hash no son iguales, se niega el acceso con el mensaje Contraseña no válida.

Nota: Para ilustrar la lógica, aquí tomamos una base de datos local o personalizada. La misma lógica también se puede implementar con la base de datos normal como MongoDB, MySql, etc.

Ejemplo: Este ejemplo ilustra cómo iniciar sesión con una contraseña sin formato cuando la contraseña almacenada en la base de datos está en formato (hash + salt).

javascript

const util = require('util')
const crypto = require('crypto')
const express = require('express')
const bodyParser = require('body-parser')
const repo = require('./repository')
 
const app = express()
const scrypt = util.promisify(crypto.scrypt)
const port = process.env.PORT || 3000
 
// The body-parser middleware to parse form data
app.use(bodyParser.urlencoded({ extended: true }))
 
// Get route to display HTML form to sign in
app.get('/signin', (req, res) => {
    res.send(`
    <div>
      <form method='POST'>
        <div>
          <div>
            <label id='email'>Username</label>
          </div>
          <input type='text' name='email'
            placeholder='Email' for='email'>
        </div>
        <div>
          <div>
            <label id='password'>Password</label>
          </div>
          <input type='password' name='password'
          placeholder='Password' for='password'>
        </div>
        <div>
          <button>Sign In</button>
        </div>
      </form>
    </div>
  `)
})
 
// Post route to handle form submission logic and
app.post('/signin', async (req, res) => {
 
    // Email and password submitted by the user
    const { email, password } = req.body
 
    // Find record by given unique username or email
    const user = await repo.findBy({ email })
    console.log(user)
 
    // If record not found by given username
    if (!user) {
        return res.send('User Not Exist')
    }
 
    // Hashed and salt of database password
    const [hashed, salt] = user.password.split('.')
 
    // Hashing raw password submitted by the user
    // to sign in third argument is the key length
    // that must be same when hashing the password
    // to store it into the database when user sign up
    const hashedBuff = await scrypt(password, salt, 64)
    console.log(hashed)
    console.log(hashedBuff.toString('hex'))
 
    // Compare saved hashed of database and
    // obtained hashed
    const isValid = hashed === hashedBuff.toString('hex')
 
    if (isValid) {
        return res.send('Sign In successfully')
    }
    return res.send('Invalid Password')
})
 
// Server setup
app.listen(port, () => {
    console.log(`Server start on port ${port}`)
})

Nombre de archivo: repository.js Este archivo contiene toda la lógica relacionada con la creación de una base de datos local y cómo interactuar con ella.

javascript

// Importing node.js file system, util,
// crypto module
const fs = require('fs')
const util = require('util')
const crypto = require('crypto')
 
// Convert callback based scrypt method
// to promise based method
const scrypt = util.promisify(crypto.scrypt)
 
class Repository {
 
    constructor(filename) {
 
        // The filename where datas are
        // going to store
        if (!filename) {
            throw new Error(
'Filename is required to create a datastore!')
        }
 
        this.filename = filename
 
        try {
            fs.accessSync(this.filename)
        } catch (err) {
 
            // If file not exist it is created
            // with empty array
            fs.writeFileSync(this.filename, '[]')
        }
    }
 
    async findBy(attrs) {
 
        // Read all file contents of the datastore
        const jsonRecords = await
            fs.promises.readFile(this.filename, {
            encoding: 'utf8'
        })
 
        // Parsing json records in javascript
        // object type records
        const records = JSON.parse(jsonRecords)
 
        // Iterating through each record
        for (let record of records) {
            let found = true
 
            // Iterate through each given
            // propert for each record
            for (let key in attrs) {
 
                // If any given property not matches
                // with record record is discarded
                if (record[key] !== attrs[key]) {
                    found = false
                }
            }
            // If 'found' remains true after iterating
            // through each given property that
            // means record found
            if (found) {
                return record
            }
        }
    }
}
 
// The 'datastore.json' file created at runtime
// if it not exist, here we try to fetch
// information from database using some properties
// that means database(datastore.json) already
// exist and there are also records in it.
module.exports = new Repository('datastore.json')

Ejecute el archivo index.js con el siguiente comando: 
 

node index.js

Nombre de archivo: paquete.json
 

archivo paquete.json

Base de datos: 

Base de datos

Producción: 

Aquí enviamos tres formularios individualmente con diferentes combinaciones de nombre de usuario y contraseña y obtenemos el resultado como se muestra en la imagen respectivamente.

Iniciar sesión con un nombre de usuario no válido

Iniciar sesión con un nombre de usuario válido pero una contraseña no válida

Iniciar sesión con usuario y contraseña válidos

Páginas redirigidas:
 

Respuesta al iniciar sesión con un nombre de usuario no válido

Respuesta al iniciar sesión con un nombre de usuario válido pero una contraseña no válida

Respuesta al iniciar sesión con nombre de usuario y contraseña válidos

Publicación traducida automáticamente

Artículo escrito por hunter__js y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *