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

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,提示用户未登录

  • 目录结构

说明: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开发团队

芦苇科技-广州专业互联网软件服务公司

抓住每一处细节 ,创造每一个美好

关注我们的公众号,了解更多

想和我们一起奋斗吗?lagou搜索“ 芦苇科技 ”或者投放简历到 server@talkmoney.cn 加入我们吧

关注我们,你的评论和点赞对我们最大的支持

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值