Express security verification -- password encryption and authentication

bcrypt password encryption

In practical applications, it is not safe to store user passwords directly in plaintext. Here is how to use password parsing and parsing

  1. Installing the bcrypt module
yarn add bcrypt
  1. Encryption and parsing function
    You need to encapsulate promise to avoid errors caused by asynchrony
exports.hash = (myPlaintextPassword) => {
    return new Promise((resolve, reject) => {
    //The second parameter is salt
        bcrypt.hash(myPlaintextPassword, 10, function (err, hash) {
            if(err){
                reject(err)
            }else{
            //If successful, the encrypted hash value will be returned
                resolve(hash)
            }
        })
    })
}

exports.compare=(myPlaintextPassword,hash)=>{
    return new Promise((resolve,reject)=>{
        bcrypt.compare(myPlaintextPassword,hash,(err,result)=>{
            if(err){
                reject(err)
            }else{
                resolve(result)
            }
        })
    })
}
  1. Encrypt the returned password in the registration interface
const signup = async (req, res, next) => {
    res.set('content-type', 'application/json;charset=utf-8')

    const { username, password } = req.body
    //Password encryption
    const bcryptPaaword = await hash(password)
    const isexit = await UserModel.findOne({ username })
    if (isexit) {
        res.render('fail', {
            data: 'User name already exists!'
        })
    } else {
        const result = await UserModel.signup({ username, password: bcryptPaaword })
        res.render('suc', {
            data: JSON.stringify(
                {
                    msg: 'login was successful'
                }
            )
        })
    }

}

The method of parsing the login interface will be described in the authentication below

Cookie session authentication

The server generates a session from the user name or other information, and compares the information for authentication each time the user requests.

  1. First install the cookie session third-party package
yarn add cookie-session
  1. On app JS
var cookieSession = require('cookie-session')

app.use(cookieSession({
  name: 'session',
  keys: ['key1', 'key2']
}))

There is a hole in this area. The registration here needs to be above the route registration, otherwise an error will be reported.

  1. After successful registration, the session is stored in the code after each successful login.
const login = async (req, res, next) => {
    res.set('content-type', 'application/json;charset=utf-8')
    const { username, password } = req.body
    const result = await UserModel.findOne({ username })
    if (result) {
        const { password: hashPassword } = result
        //Compare passwords after hash encryption
        const isTrue = await compare(password, hashPassword)
        if (isTrue) {
            req.session.username=username
            res.render('suc', {
                data: JSON.stringify({
                    msg: 'Login successful',
                    username,
                    token
                })
            })
        } else {
            res.render('fail', {
                data: JSON.stringify({
                    msg: 'Wrong user name or password'
                })
            })
        }
    } else {
        res.render('fail', {
            data: JSON.stringify({
                msg: 'Wrong user name or password'
            })
        })
    }
}
  1. Create authentication Middleware
    Create a new auth JS, let the request to be authenticated go through auth authentication before each request. If the previously stored username exists, the authentication passes. Otherwise, return the information to let the user log in again
const auth=(req,res,next)=>{
    if(req.session.username){
    //Release, continue request
        next()
    }else{
        res.render('auth', {
            data: JSON.stringify({
                msg: 'No permission!Please login!'
            })
        })
    }
}


//In routes, the auth request is passed before the list request
router.get('/list', auth,list)

Using cookie session for authentication is rarely used now. The reason is that under multi-user use, continuously storing sessions in the server will cause excessive pressure on the server. At present, the more popular authentication method is token

Token authentication

Token authentication is to generate a token and return it to the front end after the user logs in successfully. After that, every request from the front end needs to carry a token. If it passes the verification, the request can continue. The token does not have to be stored in the server, but is stored by the front end through the browser storage technology.

  1. Install the JSON webtokn package
yarn add jsonwebtoken

The encryption of token includes symmetric encryption and asymmetric encryption.
In short, symmetric encryption is actually the same key used for encryption and decryption, while asymmetric encryption is inconsistent. For this asymmetric encryption, we use public key and private key.

  1. Install openssl
    Download address: http://slproweb.com/products/Win32OpenSSL.html
    The installation and setting environment variables of this piece will not be repeated. Baidu or view this article by yourself
    https://blog.csdn.net/qq_39081974/article/details/81059022
  2. Create the keys folder and execute the following commands to create the public key and private key
utilize openssl Generate public and private keys 
Generate public key: openssl genrsa -out rsa_private_key.pem 1024 
Generate private key: openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
  1. Create and parse token functions
exports.createToken=(username)=>{
//Read the private key and generate a token according to the user name and private key. An algorithm needs to be passed in when generating the private key
    const private=fs.readFileSync(path.join(__dirname,'../keys/rsa_private_key.pem'))
    let token=jwt.sign({username},private,{ algorithm: 'RS256' })
    return token
}

exports.verifyToken=(token)=>{
//Read the public key and parse the token according to the token and the public key. There is no need to pass in the algorithm
    const public=fs.readFileSync(path.join(__dirname,'../keys/rsa_public_key.pem'))
    console.log(jwt.verify(token,public));
    return jwt.verify(token,public)
}
  1. Authentication in auth
    Like the above cookie session authentication, auth requests need to be filtered
    Get the token in the request header for parsing. If there is an error, it will directly return no permission
const auth = (req, res, next) => {
    const token = req.headers.token
    try {
        verifyToken(token)
        next()
    } catch (error) {
        res.render('auth', {
            data: JSON.stringify({
                msg: 'No permission!Please login!'
            })
        })
    }
}

Keywords: node.js OpenSSL jwt

Added by wellmoon on Fri, 11 Feb 2022 10:10:44 +0200