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
}

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();
  });
}

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;

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
        });
    }
}

权限相关
展示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

书籍路由函数
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 });
    }
}

声明文档

// 导入 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

效果图
nodeJs+jwt实现小程序tonken鉴权_第1张图片
nodeJs+jwt实现小程序tonken鉴权_第2张图片

你可能感兴趣的:(小程序,node.js)