node注册登录到jwt(token)鉴权实现

前言

本内容是在egg框架中的相关实现,主要是在登录注册时利用bcrypt库对密码的处理,和利用egg-jwt实现token的生成和校验

一、登录注册实现

1,注册对密码加

注册主要是把用户提交的信息保存起来,重点是密码的处理,把密码加密后保存在数据库有利于更好地保护我们的用户信息。接下来,我们将使用Bcrypt为我们的用户密码加盐并散列。

Bcrypt早在1996年就存在,并且经过多年的大量网站的使用和验证,鲜有报道出来的问题。可以说他的这一套算法是很安全的。

散列(hash) 的意思是给一段普通文字使用算法加密,使他变成一个固定长度的字符串。不管这段文字有多长,经过算法处理后的最终的结果都将是相同长度。并且每次的结果都将完全相同。

盐 (salt) 是一个随机的字符串。如果你在hash的时候加入盐作为干扰的话,那么结果就不会再保持相同了。盐会被自动加到hash里面

js 复制代码
// 安装bcryptjs
npm install bcryptjs

// 引入
const bcrypt = require('bcryptjs');

// 注册接口
register(params) {
    // bcrypt 库 对密码加密
    const { ctx } = this
    const params = ctx.request.body
    const saltRounds = 10
    var hash = bcrypt.hashSync(params.password, saltRounds);
    var user = await ctx.model.Users.create({ // 数据入库
      name: params.name,
      password: hash,
      ...params
    });
    ctx.success('注册成功')
}

saltRounds。saltRounds 代表加密所需的时间,saltRounds越大,加密所需时间越长,加密后的密码也就越安全。但是我们也不想让用户永远等着我们加密密码,所以一般使用默认值10就可以。

2,登录对密码校验和token下发

密码校验使用 bcrypt.compare(password1, password2) 返回布尔值,如果密码和hash吻合的话,就返回true,反之false。

生成token用 egg-jwt

js 复制代码
// 安装
npm i egg-jwt -S

// 配置config/plugins.js
jwt: {
  enable: true,
  package: 'egg-jwt',
}

// 配置 config/config.default.js
config.jwt = {
    secret: 'xxxxxxxxx', // 自定义 token 的加密条件字符串
    expiresIn: '7d', // 过期时间
}
js 复制代码
login() {
    const { ctx, app } = this
   // 查询数据库是否有该用户
    var targetUser = await ctx.model.Users.findOne({
      where: {
        account: params.account
      }
    });
    if (!targetUser) { // 用户不存在
      return ctx.error('用户或密码错误');
    }
    const params = ctx.request.body
    // 密码一致性校验。password1用户提交的密码,password2是数据库保存的密码(一串hash密文)
    const match = await bcrypt.compare(params.password, targetUser.dataValues.password);
    // 返回**布尔值**,如果密码和hash吻合的话,就返回true,反之false。
    if (match) {
      // 获取config中jwt配置
      const { secret, expiresIn } = app.config.jwt;
      // 生成token,往token里存储用户信息,secret'秘钥,expiresIn 过期时间
      const token = app.jwt.sign(targetUser.dataValues, secret, { expiresIn });
      
      // 把token返回前端
      targetUser.dataValues.token = token;
       // 过滤返回数据 密码,删除时间
      delete targetUser.dataValues.password;
      ctx.success(targetUser)
    } else {
      return ctx.error('用户或密码错误');
    }
}

3,接口需要token校验的话,在路由中间件注入jwt,请求头需要加上Authorization: Bearer + 空格 + token

js 复制代码
// routes/users.js
module.exports = app => {
  const { router, controller, jwt } = app;
  // 获取用户列表
  router.get("xxx/list", jwt, controller.users.getUserList); // jwt以中间件注入,在调用时会触发token校验

4,无感刷新token

1, 使用两个token: accessToken和refreshToken

  • accessToken用来鉴权,其有效期很短,即使被盗,影响也较小
  • refreshToken只用来刷新accessToken的时间.其有效期很长,作用只是用来刷新token,即使被盗影响也不大

新增刷新接口

js 复制代码
// 签发无感刷新使用的token
function generateReFreshToken(user) { 
    const refreshOptions = { 
        expiresIn: '10d'
    }
    const payload = { username: user.username };
    return jwt.sign(payload, secret, refreshOptions); 
}

// 无感刷新token。该接口需要带上refreshToken,jwt会验证refreshToken是否过期
app.get('/refreshToken', jwt, (req,res) => {
  const {username,password} = req.user
  // 新token
  const token = generateToken({username,password})
  // 新refreshToken
  const refreshToken = generateReFreshToken({username,password})
  res.send({
    data: {
      token,refreshToken
    },
    success: true,
  })
})

//登录接口也要改一下 登录时将refreshToken也返回
相关推荐
理想不理想v4 小时前
vue种ref跟reactive的区别?
前端·javascript·vue.js·webpack·前端框架·node.js·ecmascript
暮毅8 小时前
10.Node.js连接MongoDb
数据库·mongodb·node.js
~甲壳虫14 小时前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
~甲壳虫15 小时前
说说webpack中常见的Loader?解决了什么问题?
前端·webpack·node.js
~甲壳虫15 小时前
说说webpack proxy工作原理?为什么能解决跨域
前端·webpack·node.js
熊的猫15 小时前
JS 中的类型 & 类型判断 & 类型转换
前端·javascript·vue.js·chrome·react.js·前端框架·node.js
前端青山1 天前
Node.js-增强 API 安全性和性能优化
开发语言·前端·javascript·性能优化·前端框架·node.js
GDAL1 天前
npm入门教程1:npm简介
前端·npm·node.js
郑小憨1 天前
Node.js简介以及安装部署 (基础介绍 一)
java·javascript·node.js
lin-lins2 天前
模块化开发 & webpack
前端·webpack·node.js