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