koa2 & jwt实现用户登录和用户信息存储

  • 演示代码戳此

  • jwt技术点实现的功能如下

    • 1、server端会在前端访问部分接口时做权限认证,server端会声明不需要jwt权限验证的接口,比如login登录接口,对于需要jwt权限验证的接口,如果前端无权限,则server端会返给前端401状态码
    • 2、用户登录成功后,server端就会返回给前端一个加密了的有保质期的字符串,字符串中存储着用户登录的信息,这个字符串就是token,前端拥有未过期的token,就表明前端有访问有权限认证的接口的权限
    • 3、接下来用户再发送网络请求调用server端接口时,就会携带token,用来表明自己的身份
  • 实现功能点 1 的技术细节如下

    • 使用插件 koa-jwt

      1
          npm i koa-jwt --save
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
          const jwtKoa = require('koa-jwt')
          const { SECRET } = require('./config/constants')
         
          // koa实现jwt验证
          app.use(jwtKoa({
            // 密匙
            secret: SECRET
          }).unless({
            // 自定义忽略jwt验证的目录
            path: [/^\/users\/login/]
          }))
  • 实现功能点 2 的技术细节如下

    • 使用插件 koa-jwt

      1
          npm i jsonwebtoken --save

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
          const jwt = require('jsonwebtoken')
          const { SECRET } = require('../config/constants')

          // 模拟登陆
          router.post('/login', async (ctx) => {
            const { userName, password } = ctx.request.body
            let userInfo = null
            // 尝试登陆
            if (userName === 'zhangsan' && password === 'abc') {
              userInfo = { userid: 1, userName: 'zhangsan', nickName: '张三' }
            }
         
            // 加密 userInfo
            let token = null
            if (userInfo) {
              token = jwt.sign(userInfo, SECRET, { expiresIn: '1h' })
            }
         
            // 登陆失败
            if (userInfo === null) {
              ctx.body = { errno: -1, msg: '登录失败' }
              return
            }
            // 登陆成功给前端返回加密的token
            ctx.body = { errno: 0, data: token }
          })
  • 实现功能点 3 的技术细节如下

    • 前端调用有jwt权限的接口需要在请求头中携带加密了的token

      1
      2
      3
          Headers: {
              Authorization: Bearer TOKEN
          }
    • server端解密token,获取其中的用户信息的技术细节如下

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
          const jwt = require('jsonwebtoken')
          const util = require('util')
          const verify = util.promisify(jwt.verify)  // 将jwt.verify函数promise化
          const { SECRET } = require('../config/constants')  // 解密密码
          // 获取用户信息
          router.get('/getUserInfo', async (ctx, next) => {
            const token = ctx.header.authorization
            try{
              // 解密token
              const payload = await verify(token.split(' ')[1], SECRET)
              ctx.body = {
                errno: 0,
                userInfo: payload
              }
            }catch(e){
              console.error(e)
              ctx.body = {
                errno: -1,
                msg: 'Verify token failed.'
              }
            }