NODE + JWT + Mongo(简单实现权限管理)

2

JWT简介

  • 官方是这样介绍的:

JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.(JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑且独立的方式,可以在各方之间作为JSON对象安全地传输信息。
此信息可以通过数字签名进行验证和信任。
JWT可以使用秘密(使用HMAC算法)或使用RSA或ECDSA的公钥/私钥对进行签名。)

  • 用途

    授权和安全传输信息

  • token的结构
    Header.Payload.Signature

    • Header
      通常由两部分组成:令牌的类型,即JWT,以及正在使用的散列算法,例如HMAC SHA256或RSA。
    • Payload
      加密的数据
    • Signature
      签名

应用

知道了JWT的用途后,我们就开始针对授权来结合node做简单的实现。

  • 版本号

    • cnpm@6.0.0
    • npm@6.4.1
    • node@11.1.0
  • 流程

    流程图

    • 用户还没登录时,只能访问首页、注册、登录接口,如下图

      首页

      注册

      登录

    • 登录过后能获取自己的信息

      获取自己信息

    • 如果没输入token,则提示没有找到token,当然可以重定位到首页

      没有找到token

    • 输入错误的token,提示用户未登录

      用户未登录

  • 目录结构

目录结构

说明:config.js为全局配置文件,user.js为Mongo数据库对应的user实体,index.js为项目入口文件。

  • config.js

        module.exports = {
            'network' : {
                'port':8080
            },
            'salt': '0vAXJ@2R%PAxL9*Y#vLc8VQuLGk0BzdD',    
            'jwtsecret': 'myjwttest',
            'database': 'mongodb://127.0.0.1:27017/test'
        };
    
  • user.js

        var mongoose = require('mongoose');
        var Schema = mongoose.Schema;
    
        // 返回一个mongo用户库实例
        module.exports = mongoose.model('User', new Schema({ 
            name: String, 
            password: String
        }));
    
  • index.js

        const express = require('express');
        const app = express();
    
        const crypto = require('crypto');
        const util = require('util');
    
        const bodyParser = require('body-parser');//request.body起效果而用
        const mongoose = require('mongoose');//MongoDB
        const jwt = require('jsonwebtoken'); // 使用jwt签名
        const config = require('./config'); // 引入配置
        const User = require('./user'); // 引入mongo用户库实例
    
        // 连接mongo
        mongoose.connect(config.database);
        // 设置加密秘钥
        app.set('superSecret', config.jwtsecret);
        //设置request.body有效
        app.use(bodyParser.urlencoded({ extended: false }));
        app.use(bodyParser.json());
    
        app.listen(config.network.port);
    
        // 首页
        app.get('/', function (req, res) {
          res.send('这里是首页http://127.0.0.1:' + config.network.port + "/api");
        });
    
        // 注册
        app.post('/register', async function (req, res) {
          if (req.body.name && req.body.password) {
    
            const salt = config.salt;
              const pwdEnc = await util.promisify(crypto.pbkdf2)(req.body.password, salt.toString('base64'), 10000, 64, 'sha256');
    
            var user = new User({
              name: req.body.name,
              password: pwdEnc
            });
            user.save(function (err) {
              if (err) throw err;
              console.log('注册成功');
              res.json({ success: true });
            });
          } else {
            res.json({ success: false, msg: "错误参数" });
          }
        });
    
        // 登录,登录成功返回JWT的Token 验证用户名密码
        app.post('/login', function (req, res) {
          User.findOne({
            name: req.body.name
          }, async function (err, user) {
            if (err) throw err;
            if (!user) {
              res.json({ success: false, message: '未找到授权用户' });
            } else if (user) {
              const salt = config.salt;
              const pwdEnc = await util.promisify(crypto.pbkdf2)(req.body.password, salt.toString('base64'), 10000, 64, 'sha256');
    
              if (user.password != pwdEnc) {
                res.json({ success: false, message: '用户密码错误' });
              } else {
    
                var token = await util.promisify(jwt.sign)({
                  user: user,
                }, app.get('superSecret'), {
                  expiresIn: '4h',
                });
                res.json({
                  success: true,
                  message: '请使用您的授权码',
                  token: token
                });
              }
            }
          });
        });
    
        //  创建需要授权的接口
        var apiRoutes = express.Router();
    
        //校验机制
        apiRoutes.use(async function (req, res, next) {
    
          // 获取传过来的token
          var token = req.headers['x-access-token'];
    
          if (token) {
            // 解码token获取用户信息 decoded为加密前的内容
            util.promisify(jwt.verify)(token, app.get('superSecret')).then(function(data){
              req.decoded = data;
              next(); //继续下一步路由
            }).catch((error)=>{
              res.status(400).json({message: '用户未登录',error: error});
            });
    
          } else {
            // 没有拿到token 返回错误 
            return res.status(403).send({
              success: false,
              message: '没有找到token.'
            });
    
          }
        });
    //获取加密的信息
    apiRoutes.get('/', function (req, res) {
      req.decoded.user.password = undefined;
      res.json(req.decoded.user);
    });

    //获取所有用户
    apiRoutes.get('/list', function (req, res) {
      User.find({}, function (err, users) {
        res.json(users);
      });
    });

    // 注册API路由
    app.use('/api', apiRoutes);


```


广州芦苇科技Java开发团队

芦苇科技-广州专业软件外包服务公司

提供微信小程序、APP应用研发、UI设计等专业服务,专注于互联网产品咨询、品牌设计、技术研发等领域

访问 www.talkmoney.cn 了解更多

万能说明书 | 早起日记Lite | 凹凸壁纸 | 言财

你可能感兴趣的

空对空 · 12月7日

我想问一下 你们这个调试工具叫什么

回复

無聲锝等待 · 12月7日

postman

回复

空对空 · 12月8日

有中文版的?

回复

0

postman本身用法并太复杂,看下帮助大概就可以使用了

广州芦苇科技后台 作者 · 12月8日
载入中...