welldum 2019-06-27
官方给出的定义是:
JSON Web Token(JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、独立的方式,用于安全地在当事人之间传递信息作为一个JSON对象。这些信息可以被验证和信任,因为它是数字签名的。JWTs可以使用一个secret (使用HMAC算法)或使用RSA的公钥/私钥对来签名。 文中我们使用公私钥的加密方式。
由下面三个部分组成一个token字符串
Header
Payload ,包含三个类型,自定义部分可以存储一些信息,如:用户信息、角色等;
Signature
这里直接使用官网的图
这里使用express来创建一个服务
创建一个入口文件,主要用于一些中间件的挂载
//index.js
const express = require('express')
const app = express()
// 使用body-parser获取请求body
const bodyParser = require('body-parser');
const cookieParser = require('cookie-parser')
// 引入路由中间件
const routerAdmin = require('./app/router-admin')
app.use(bodyParser.json()); // for parsing application/json
app.use(bodyParser.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.use(cookieParser())
// 加载路由模块
app.use('/admin',routerAdmin);
app.listen(3000,function(){
console.log('port 3000 start')
})然后创建一个 app/router-admin.js 生成需要用到认证的路由中间件,这里我是在mongodb中取的用户信息,也可以自行模拟数据
//router-admin.js
const express = require('express')
const router = express.Router()
var MongoClient = require('mongodb').MongoClient;
const jwt = require('jsonwebtoken')
const fs = require('fs')
// const secretStr = 'sdfsjfklsjfiewjwoieow'
// 根据mongodb生成的_id查询数据
var ObjectId = require('mongodb').ObjectId
var url = "mongodb://localhost:27017/";
var payload = {
user : 'william',
admin : true
}
router.post('/login',function(req,res){
let name = req.body.name,
pwd = req.body.pwd;
var cert = fs.readFileSync('./private.key')
MongoClient.connect(url, function(err, db) {
if (err) throw err;
var dbo = db.db("blog");
var noSqlStr = {name:name,pwd:pwd}
dbo.collection("userlist"). find(noSqlStr).toArray(function(err, result) { // 返回集合中所有数据
if (err) throw err;
// console.log(result);
// 验证通过,服务端回传token
if(!!result.length){
var token = jwt.sign(payload, cert, { algorithm: 'RS256' ,expiresIn:'30s'});
res.send({
status : true,
msg : '',
token : token
})
}
db.close();
});
});
})
// 验证jsonwebtoken是否过期的中间件,在login接口后面执行,除了login接口的请求外,其他接口都需要验证token
router.use(function jwtVerify(req, res, next) {
let token = req.get('token')
console.log(token)
var cert = fs.readFileSync('./public.key');
// 先解密
jwt.verify(token, cert,function(err,decoded){
if(err || !decoded) res.send({data:null,status:false,msg:err})
if(decoded.user == payload.user){
next();
}
});
});
router.get('/search',function(req,res){
res.send({data:'查询成功',msg:'',status:true})
})
module.exports = router因为这里使用的是公私钥的加密方式,需使用ssh-keygen生成公私钥
私钥生成:ssh-keygen -t rsa -b 2048 -f private.key
公钥生成:openssl rsa -in private.key -pubout -outform PEM -out public.key