• nodeJs+jwt实现小程序tonken鉴权


    nodeJs+jwt实现小程序tonken鉴权

    自我记录
    config\config.js

    // 配置文件
    module.exports = {
        DBHOST: '127.0.0.1',
        DBPORT: '27017',
        DBNAME: 'test',
        secret: 'xxxxx',// 小程序的appSecret
        AppID: 'xxxxx',// 小程序的appId
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    token中间件
    middlewares\checkTokenMiddleware.js

    //导入 jwt
    const jwt = require('jsonwebtoken');
    //读取配置项
    const {secret} = require('../config/config');
    //声明中间件
    module.exports = (req, res, next) => {
      //获取 token 采用的是 Bearer + ' ' + token形式
      const Authorization = req.get('Authorization');
      //判断
      if (!Authorization) {
        return res.json({
          code: 401,
          msg: '暂无权限',
          data: null
        })
      }
      //校验 token
      const token = Authorization.split(' ')[1]
      jwt.verify(token, secret, (err, data) => {
        //检测 token 是否正确
        if (err) {
          return res.json({
            code: 403,
            msg: 'token失效',
            data: null
          })
        }
        //保存用户的信息
        req.user = data; // req.session  req.body
        //如果 token 校验成功
        next();
      });
    }
    
    • 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
    • 30
    • 31
    • 32
    • 33

    routes路由文件
    routes\user.js

    const express = require('express');
    const router = express.Router();
    
    //导入 用户路由函数
    const user_handler = require('../router_handler/user');
    // 注册新用户
    router.post('/reguser', user_handler.reguser);
    
    //登录操作TODO
    router.post('/login', user_handler.login);
    //退出登录TODO
    router.post('/logout',user_handler.logout );
    
    module.exports = router;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    user路由函数
    router_handler\user.js

    //导入 用户的模型
    const UserModel = require('../models/UserModel');
    //导入配置文件
    const { secret, AppID } = require('../config/config')
    //导入 jwt
    const jwt = require('jsonwebtoken');
    //导入请求
    const request = require('request')
    //导入 shortid
    const shortid = require('shortid');
    //注册用户
    exports.reguser = async (req, res) => {
        try {
            const js_code = req.body.code;
    
            if (!js_code) {
                return res.json({
                    code: 400,
                    message: '缺少 js_code 参数'
                });
            }
            // 发送请求并处理响应
            sendRequest(js_code, handleResponse(res));
        } catch (err) {
            console.error('Error registering user:', err);
            res.json({
                code: 400,
                msg: '注册失败,请稍后再试~~',
                data: null
            });
        }
    }
    
    const sendRequest = (js_code, callback) => {
        request(`https://api.weixin.qq.com/sns/jscode2session?appid=${AppID}&secret=${secret}&js_code=${js_code}&grant_type=authorization_code`, callback);
    }
    
    const handleResponse = (res) => {
        return async (error, response, body) => {
            if (error) {
                console.error('Error sending request:', error);
                return res.json({
                    code: 500,
                    message: '请求失败,请稍后再试~~'
                });
            }
    
            if (response.statusCode !== 200) {
                return res.json({
                    code: 400,
                    message: '获取用户信息失败'
                });
            }
    
            try {
                const bodyInfo = JSON.parse(body);
                const openId = bodyInfo.openid;
                if (!openId) {
                    return res.json({
                        code: 400,
                        msg: 'code失效',
                        data: null
                    });
                }
                const userData = await UserModel.findOne({ openId });
                if (userData) {
                    const token = await getToken(userData.openId, userData.id)
                    const result = await UserModel.updateOne({ id: userData.id }, { token: token })
                    if (!result.acknowledged) {
                        throw new Error('写入操作未被确认');
                    }
                    return res.json({
                        code: 200,
                        msg: '该用户已存在并生成新的token',
                        data: token
                    });
                }
    
                const id = shortid.generate()
                const token = await getToken(openId, id)
                const data = await UserModel.create({ openId, token, id });
                res.json({
                    code: 200,
                    msg: '获取成功',
                    data: data.token
                });
            } catch (err) {
                console.error('Error registering user:', err);
                res.json({
                    code: 400,
                    msg: '注册失败,请稍后再试~~',
                    data: null
                });
            }
        };
    }
    // 创建当前用户的 token
    const getToken = async (openId, id) => {
        return await jwt.sign({
            openId,
            id
        }, secret, {
            expiresIn: 60 * 60 * 24 * 7
        });
    }
    
    // 登录待测试
    exports.login = async (req, res) => {
        try {
            // 获取用户名和密码
            const { openId } = req.body;
            // 查询数据库
            const data = await UserModel.findOne({ openId });
            // 判断 data
            if (!data) {
                return res.json({
                    code: 400,
                    msg: '用户名或密码错误',
                    data: null
                });
            }
            // 创建当前用户的 token
            const token = await getToken(data.openId, data.id)
    
            // 响应 token
            res.json({
                code: 200,
                msg: '登录成功',
                data: token
            });
        } catch (err) {
            // 处理错误
            console.error('Error logging in:', err);
            res.json({
                code: 500,
                msg: '登录失败',
                data: null
            });
        }
    }
    // 退出待测试
    exports.logout = async (req, res) => {
        try {
            // 销毁 token
            await new Promise((resolve, reject) => {
                req.token.destroy((err) => {
                    if (err) {
                        reject(err);
                    } else {
                        resolve();
                    }
                });
            });
    
            // 响应退出成功
            res.json({
                code: 200,
                msg: '退出成功',
                data: null
            });
        } catch (err) {
            // 处理错误
            console.error('Error logging out:', err);
            res.json({
                code: 500,
                msg: '退出失败',
                data: null
            });
        }
    }
    
    • 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
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170

    权限相关
    展示openId 对应用户的书籍信息
    书籍路由文件
    routes\book.js

    const express = require('express')
    
    const router = express.Router()
    
    // 导入路由函数 
    const book_handler = require('../router_handler/book')
    // 导入验证token的中间件
    const checkTokenMiddleware = require('../middlewares/checkTokenMiddleware')
    // 一个路由的组成有 请求方法 , 路径 和 回调函数 组成
    // app.(path,callback)
    // 注册新书籍
    router.post('/addbook',checkTokenMiddleware, book_handler.addBook)
    // 获取列表
    router.get('/getBook',checkTokenMiddleware, book_handler.getBook);
    
    // 获取单独的
    router.get('/book/:id',checkTokenMiddleware, book_handler.getOneBook);
    
    // 删除单独的
    router.delete('/book/:id',checkTokenMiddleware, book_handler.delBook);
    
    module.exports = router
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    书籍路由函数
    router_handler\book.js

    const BookModel = require('../models/BookModel');
    // 单条新增
    exports.addBook = async (req, res) => {
        try {
            const data = await BookModel.create({
                ...req.body, user: req.user.openId
            })
            return res.json({ code: 200, message: "添加成功", data: data });
        } catch (err) {
            // 处理错误并打印错误信息
            // 处理错误并返回失败的 JSON 响应
            console.error("Error creating book:", err);
            return res.json({ code: 500, message: "添加失败", error: err.message });
        }
    }
    // 获取列表
    exports.getBook = async (req, res) => {
        try {
            const data = await BookModel.find({ user: req.user.openId })
            return res.json({ code: 200, message: "查询成功", data });
        } catch (err) {
            console.error("Error creating book:", err);
            return res.json({ code: 500, message: "查询失败", error: err.message });
        }
    }
    // 获取ID
    exports.getOneBook = async (req, res) => {
        let { id } = req.params;
        let { openId } = req.user
        try {
            const data = await BookModel.findOne({ _id: id, user: openId })
            if (!data) {
                return res.json({ code: 404, message: "未找到匹配的书籍" });
            }
            return res.json({ code: 200, message: "查询成功", data });
        } catch (err) {
            console.error("Error creating book:", err);
            return res.json({ code: 500, message: "查询失败", error: err.message });
        }
    }
    // 删除ID
    exports.delBook = async (req, res) => {
        let { id } = req.params;
        let { openId } = req.user
        try {
            const result = await BookModel.deleteOne({ _id: id, user: openId })
            if (result.deletedCount === 1) {
                // 成功删除
                return res.json({ code: 200, message: "删除成功", data: {} });
            } else {
                // 没有匹配的文档
                return res.json({ code: 404, message: "未找到匹配的文档" });
            }
        } catch (err) {
            console.error("Error deleting book:", err);
            return res.json({ code: 500, message: "删除失败", error: err.message });
        }
    }
    
    • 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
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58

    声明文档

    // 导入 mongoose
    const mongoose = require('mongoose')
    
    // 创建文档的结构对象
    // 设置集合中 文档的属性 以及类型值
    let UserSchema = new mongoose.Schema({
        openId: String, // 添加 openId 字段
        token: String,
        id: String,
    });
    // 创建模型对象 : mongoose 会使用集合的复数去创建集合
    let UserModel = mongoose.model("users", UserSchema);
    
    // 暴露模型对象
    module.exports = UserModel
    
    
    -------------------------------------------------------书籍相关----------------------------------
    // 导入 mongoose
    const mongoose = require('mongoose')
    
    // 5. 创建文档的结构对象
    // 设置集合中 文档的属性 以及类型值
    let BookSchema = new mongoose.Schema({
        name: {
            type: String,
            required: true, // 必填
            unique: true // 独一无二 新集合才可以
        },
        author: {
            type: String,
            default: '匿名' // 默认值
        },
        gender: {
            type: String,
            enum: ['男', '女'] // 枚举 必须是里面的内容  
        },
        price: Number,
        is_hot: Boolean,
        user: {
            type: String, // 或者其他与用户标识匹配的类型
            required: true
        },
        // tag: Array,
        // pub_time: Date,
    });
    // 6.创建模型对象 : mongoose 会使用集合的复数去创建集合
    let BookModel = mongoose.model("books", BookSchema);
    
    // 暴露模型对象
    module.exports = BookModel
    
    • 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
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51

    效果图
    在这里插入图片描述
    在这里插入图片描述

  • 相关阅读:
    最优传输(Optimal Transport)
    使用RCurl和R来爬虫视频
    sql server 2008 安装,java jdbc 连接测试
    ElasticSearch学习(一)
    Python的requests库使用总结
    B树与B+树
    Lyx使用bib插入参考文献
    git merge本地合并分支出现文件冲突处理方法
    基于matlab如何判断闰年方法
    大厂钟爱的全链路压测有什么意义?四种压测方案详细对比分析
  • 原文地址:https://blog.csdn.net/zhgweb/article/details/133316260