基于express封装的用户鉴权功能的原理:
1、用jsonwebtoken生成token
2、用passport、passport-jwt验证token是否过期或失效
3、用jsonwebtoken解析出token中的用户信息,比如用户id
1. 用户登录成功后,使用jsonwebtoken生成token并返回
Install
npm install jsonwebtoken
usage
const jwt = require('jsonwebtoken');
jwt.sign({
exp: Math.floor(Date.now() / 1000) + (60 * 60),
data: 'foobar'
}, 'secret', (err, token) => {
console.log(toten);
});
jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: 60 * 60 }, (err, token) => {
console.log(token)
});
jwt.sign({
data: 'foobar'
}, 'secret', { expiresIn: '1h' }, (err, token) => {
console.log(token)
});
example:
const express = require('express');
const router = express.Router();
const Admin = require('../../models/admin');
// 对密码进行加密 存储到数据库
const bcrypt = require('bcrypt');
const secret = require('../../config/constant').secret;
// 登录成功后返回token,使用jsonwebtoken
const jwt = require('jsonwebtoken');
Admin.find({username: 'admin'}).then(admin => {
if (!admin.length) {
let AdminUser = new Admin({
username: 'admin',
password: 'admin123',
});
bcrypt.genSalt(10, function(err, salt) {
bcrypt.hash(AdminUser.password, salt, function(err, hash) {
// Store hash in your password DB.
AdminUser.password = hash;
});
AdminUser.save();
});
}
});
/**
* login
* $route POST /api/admin/login
* @desc 返回json
* @access public
*/
router.post('/login', (req, res) => {
console.log(req.body, '9');
Admin.findOne({
username: req.body.userName,
}).then(data => {
console.log(data, '000');
if (data) {
bcrypt.compare(req.body.password, data.password).then(result => {
if (result) {
console.log('1')
// 登录成功返回token,使用jsonwebtoken签名获取token
jwt.sign({id: data._id, username: data.userName}, 'secret', {expiresIn: 3600}, (err, token) => {
res.json({
code: 0,
token: 'Bearer ' + token, // token的设置必须是‘Bearer ’开头
msg: 'login success',
});
})
} else {
console.log('1')
res.json({
code: 102,
data: null,
msg: '密码错误',
});
}
})
} else {
console.log('2')
res.json({
code: 101,
data: null,
msg: '用户名错误',
});
}
}).catch(err => {
console.log(err, 'err')
});
})
module.exports = router;
2 token验证,使用passport passport-jwt
Install
npm install passport passport-jwt
usage
// 入口文件
const passport = require('passport');
app.use(passport.initialize());
require('./config/passport')(passport);
// passport.js
const JwtStrategy = require('passport-jwt').Strategy,
ExtractJwt = require('passport-jwt').ExtractJwt;
const mongoose = require('mongoose');
const User = require('../models/admin').model('admin');
const secret = require('../config/constant').secret;
let opts = {}
opts.jwtFromRequest = ExtractJwt.fromAuthHeaderAsBearerToken();
opts.secretOrKey = secret;
module.exports = passport => {
passport.use(new JwtStrategy(opts, (jwt_payload, done) => {
console.log(jwt_payload, 'jwt_payload')
User.findById(jwt_payload.id, (err, user) => {
console.log(user, 'user')
if (err) {
return done(err, false);
}
if (user) {
return done(null, user);
} else {
return done(null, false);
// or you could create a new account
}
});
}));
}
//验证请求 passport.authenticate('jwt', {session: false})
app.post('/login',
passport.authenticate('local', { failureRedirect: '/login' }),
(req, res) => {
res.redirect('/');
});
example:
/**
* current
* $route GET /api/admin/current
* @desc 返回json
* @access private
*/
router.get('/current', passport.authenticate('jwt', {session: false}), (req, res) => {
res.json({
id: req.user._id,
username: req.user.username
})
})
测试如下: