• 在node.js中配置Token验证的两种方式


    1. 生成Token jwt passport实现生成和验证Token

    jsonwebtoken

    1. 安装
    npm i jsonwebtoken
    
    • 1
    1. 引入
    const jwt = require('jsonwebtoken')s
    
    • 1
    1. 定义规则
    const rule = { id: result[0].id, name: result[0].name }
    
    • 1

    由于id,和name都是通过数据库获取过来的,所以用的这种方式

    1. 设置jwt.sign方法/生成token
    jwt.sign("规则", "加密名字", "过期时间", "箭头函数")
    
    • 1
            jwt.sign(rule, key.secretOrkey, { expiresIn: 3600 }, (err, token) => {
              if (err) return err.message
              return res.send({
                code: 1,
                msg: `Bearer ${token}`
              })
            })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这里的rule就是上面所说的校验规则,key.secretOrkey就是加密名字,只不过封装到了外部,expiresIn:3600,就说明是3600秒,msg返回的就是生成的Token

    1. 验证token
    // $router get api/user/current
    // @desc return current user
    // @access private
    router.get("/current", "验证Token", (req, res) => {
      res.send({
        code: 1,
        msg: '验证成功'
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    我们需要在"验证Token"那里对Token进行验证

    7. 使用passpport-jwt||passport验证Token

    passport

    passport-jwt

    1. 安装
    npm install passport-jwt
    npm i passport
    
    • 1
    • 2
    1. 使用
      这是从npm摘抄过来的的示例方法
      passport
    passport.use(new LocalStrategy(
      function(username, password, done) {
        User.findOne({ username: username }, function (err, user) {
          if (err) { return done(err); }
          if (!user) { return done(null, false); }
          if (!user.verifyPassword(password)) { return done(null, false); }
          return done(null, user);
        });
      }
    ));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    这个方法中的User.findOne方法可以删除,写上自己的业务逻辑,我用的是mysql,所以没有用User.findeOne方法

    初始化passport

    app.use(passport.initialize());
    
    • 1

    passport-jwt

    new JwtStrategy(options, verify)
    
    • 1
    1. 实际使用

    index.js(项目入口文件)

    const passport = require("passport")
    
    //在入口文件中配置和引用
    //初始化passport
    app.use(passport.initialize());
    require("./config/passport")(passport)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    这里单独抽离了passport配置文件,同时将上面引入的passprot进行引入

    config/passport.js

    const db = require("../db/index")
    const JwtStrategy = require('passport-jwt').Strategy
    const ExtractJwt = require('passport-jwt').ExtractJwt
    
    const key = require("../config/key")
    const opts = {}
    opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
    opts.secretOrKey = key.secretOrkey;
    
    
    module.exports = passport => {
      passport.use(new JwtStrategy(opts, (jwt_payload, done) => {
        // { id: 1, name: 'wz', iat: 1660299838, exp: 1660303438 }
        console.log(jwt_payload);
        sqlcc = `SELECT * FROM user WHERE id=${jwt_payload.id};`
        db.query(sqlcc, (err, result) => {
          console.log(result[0]);
          if (err) {
            return done(null, err.message)
          }
          if (result.length != 0) {
            return done(null, result[0])
          } else {
            return done(null, false)
          }
        })
      }));
    
    }
    
    • 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
    • 27
    • 28
    • 29

    注意,生成的token应该带有统一的格式。一个正确的token应该是这样的Bearer ${token},注意Bearer和生成的Token之间的空格。

    接下来在需要校验的地方验证Token

    // $router get api/user/current
    // @desc return current user
    // @access private
    router.get("/current", passport.authenticate("jwt", { session: false }), (req, res) => {
      res.send({
        code: 1,
        msg: req.user
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    验证token如果通过,就会执行passport.use里的方法,同时jwt_jpayload会输出结果,得到结果后,我们在用id在User表中查询数据,然后通过req.user(数据库表名)拿到。

    // { id: 1, name: 'wz', iat: 1660299838, exp: 1660303438 }
    console.log(jwt_payload);
    
    • 1
    • 2

    2. express-jwt || jsonwebtoken生成Token验证Token

    1. 安装
    npm install jsonwebtoken express-jwt
    
    • 1

    注意

    jsonwebtoken用于生成JWT字符串

    express-jwt用于将Jwt字符串解析为JSON对象

    1. 新建文件夹config/key.js
    module.exports = {
      keyOringe: "secret"
    }
    
    • 1
    • 2
    • 3

    将设置的key值暴露出去

    1. 在需要的地方引入
    const jwt = require("jsonwebtoken")
    
    • 1
        if (password == tools.setPassword(results[0].password)) {
          //如果成功,传1,页面跳转交给vue
    +      const rule = {
    +        id: results[0].id,
    +        adminname: results[0].adminname
    +      }
    
    +      const tokenstr = jwt.sign(rule, key.keyOringe, { expiresIn: 3600 })
    +      res.send({
    
            code: 1,
            msg: '登陆成功',
    +        token: tokenstr
          })
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. 调用 jwt.sign() 方法生成JWT字符串 并通过 token 属性发送给客户端
    2. 参数1: 用户的信息对象
    3. 参数2: 加密的密钥
    4. 参数3: 配置对象 可以配置当前 token 的有效期
    5. rule只是抽离出去,其实直接写也没问题

    在中间件中使用

    const { expressjwt: jwt } = require("express-jwt")
    const key = require('../config/key')
    
    
    
    router.use(jwt({
      secret: key.keyOringe,
      algorithms: ["HS256"],
    }).unless({ path: ["/admin/login", "/admin/register"] })
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    之后使用私有接口去访问

    //$route GET admin/banner/
    //@desc 修改轮播图接口
    router.get('/', (req, res) => {
      console.log(req);
      res.send({
        code: 1,
        msg: '获取用户信息成功',
        data: req.auth
      })
    })
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    这样就会返回带有用户信息的Token了!

    捕获解析JWT失败后产生的错误

    当使用express-jwt解析Token字符串时,如果客户端发送的Token字符串过期不合法,会产生一个解析失败的错误,影响项目的正常运行,可以通过Express的错误中间件,捕获这个错误并且进行相关的处理,示例代码如下:

    //在所有路由后面定义错误中间件
    //使用全局错误处理中间件 捕获解析 JWT 失败后产生的错误
    app.use((err, req, res, next) => {
      //判断是否由 Token 解析失败导致的
      if (err.name == 'UnauthorizedError') {
        return res.send({
          status: 401,
          message: '无效的Token'
        })
      }
      res.send({
        status: 500,
        message: '未知的错误'
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
  • 相关阅读:
    数据库设计三大范式
    leetcode刷题 (8.26) 二叉树
    UML_类图_时序图
    Java并发编程的艺术笔记-Java中的线程池
    数据结构Python版(三)——栈
    带你深入了解队列(c/cpp双版本模拟实现)
    带CAD转换的的坐标计算程序代码
    【JVM学习03】类加载与字节码技术
    frp内网穿透教程2022最新(含内网ssh配置与msf联动配置)
    初次接触Sharding-JDBC并实际应用
  • 原文地址:https://blog.csdn.net/liyuchenii/article/details/126312690