Express安全验证——密码加密与鉴权

bcrypt密码加密

在实际应用中,直接将用户密码以明文信息进行存储是不安全的做法,这里讲解一下如何使用密码解析与解析

  1. 安装bcrypt模块
yarn add bcrypt
  1. 加密与解析函数
    这里需要自己进行promise的封装,才能避免因为异步的原因导致出错
exports.hash = (myPlaintextPassword) => {
    return new Promise((resolve, reject) => {
    //第二个参数是盐
        bcrypt.hash(myPlaintextPassword, 10, function (err, hash) {
            if(err){
                reject(err)
            }else{
            //成功则返回加密后的hash值
                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. 在注册接口中将传回来的密码进行加密
const signup = async (req, res, next) => {
    res.set('content-type', 'application/json;charset=utf-8')

    const { username, password } = req.body
    //进行密码加密
    const bcryptPaaword = await hash(password)
    const isexit = await UserModel.findOne({ username })
    if (isexit) {
        res.render('fail', {
            data: '用户名已存在!'
        })
    } else {
        const result = await UserModel.signup({ username, password: bcryptPaaword })
        res.render('suc', {
            data: JSON.stringify(
                {
                    msg: '注册成功'
                }
            )
        })
    }

}

登录接口进行解析的方法在下面的鉴权中会一并说明

Cookie-Session鉴权

在服务端将用户名或其他信息生成session,每次用户请求时进行信息比对进行鉴权。

  1. 首先安装cookie-session第三方包
yarn add cookie-session
  1. 在app.js中进行注册
var cookieSession = require('cookie-session')

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

这块有个坑,这里的注册需要在路由注册的上方,否则会报错。

  1. 注册成功之后,在每次登录成功之后的代码中进行session的存储。
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
        //hash加密后进行密码的比对
        const isTrue = await compare(password, hashPassword)
        if (isTrue) {
            req.session.username=username
            res.render('suc', {
                data: JSON.stringify({
                    msg: '登录成功',
                    username,
                    token
                })
            })
        } else {
            res.render('fail', {
                data: JSON.stringify({
                    msg: '用户名或密码错误'
                })
            })
        }
    } else {
        res.render('fail', {
            data: JSON.stringify({
                msg: '用户名或密码错误'
            })
        })
    }
}
  1. 创建鉴权中间件
    新建一个auth.js,让需要鉴权的请求在每次请求前先经过auth鉴权,如果此前存储的username存在,则鉴权通过,否则返回让用户重新登录的信息
const auth=(req,res,next)=>{
    if(req.session.username){
    //放行,继续请求
        next()
    }else{
        res.render('auth', {
            data: JSON.stringify({
                msg: '无权限!请登录!'
            })
        })
    }
}


//在routes中,进行list请求前先经过auth请求
router.get('/list', auth,list)

使用cookie-session进行鉴权现在用法比较少,理由是多用户使用下,持续在服务器中存储session会造成服务器压力过大,目前比较流行的鉴权方式是token

Token鉴权

token鉴权是在用户登录成功之后,生成token返回给前端。之后前端每一次请求,都需要携带token,如果通过验证即可继续进行请求,token不必存储在服务器,由前端自行通过浏览器存储技术进行存储。

  1. 安装jsonwebtokn包
yarn add jsonwebtoken

token的加密有对称加密和非对称加密。
简单来说,对称加密其实就是加密和解密时所使用的密钥一致,非对称加密就是不一致,这块的非对称加密我们使用公钥和私钥。

  1. 安装openssl
    下载地址:http://slproweb.com/products/Win32OpenSSL.html
    这块的安装和设置环境变量不再赘述,自行百度或查看此文章
    https://blog.csdn.net/qq_39081974/article/details/81059022
  2. 创建keys文件夹,在里面执行以下命令,创建公钥和私钥
利用 openssl 生成公钥私钥 
生成公钥: openssl genrsa -out rsa_private_key.pem 1024 
生成私钥: openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem
  1. 创建token和解析token函数
exports.createToken=(username)=>{
//读取私钥,根据用户名和私钥生成token,生成私钥时需要传入一个算法
    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)=>{
//读取公钥,根据token和公钥解析token,不需要传入算法
    const public=fs.readFileSync(path.join(__dirname,'../keys/rsa_public_key.pem'))
    console.log(jwt.verify(token,public));
    return jwt.verify(token,public)
}
  1. 在auth中进行鉴权
    和上面cookie-session鉴权一样,需要由auth请求进行一个过滤
    获取请求头中的token进行解析,若出错则直接返回无权限
const auth = (req, res, next) => {
    const token = req.headers.token
    try {
        verifyToken(token)
        next()
    } catch (error) {
        res.render('auth', {
            data: JSON.stringify({
                msg: '无权限!请登录!'
            })
        })
    }
}
  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值