JWT身份验证原理简单讲解与nodejs简单实现

目录

  • 前言
  • JWT简单介绍
  • node中使用JWT
    • 安装jsonwebtoken包
    • 签发token
    • 验证token

前言

上一篇【基于token的持久化登录讲解及其实现】讲到token的机制,以及token的2大特性,即:只有服务器能够签发token,服务器可以验证token是否由自己签发。

可是上一篇博客编写的时候,对token的理解还不够深入,上一篇博客的token是最最最基本的token验证,而现在互联网应用的登录验证普遍使用JWT,即 JSON WEB TOKEN 的规范化验证,所以今天来学习一蛤,并且学习如何在node上编写token的签发与验证程序。

JWT简单介绍

JWT,即 JSON WEB TOKEN ,是一种规范化的无状态登录验证方式。因为以JSON的形式表示,所以JWT天然的不受编程语言的限制。

jwt中,token是一串字符串,由.号分割为三个部分,下面给出一条完整的token

完整:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid29ybGRIZWxsbyIsImlkIjoxMTQ1MTQsImlhdCI6MTU5NzM5Nzk0MSwiZXhwIjoxNTk3NjU3MTQxfQ.otN7LikyB1mmknnBXL0mVrdOSFmID-dCORD5x4R3voM

第一部分:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

第二部分
eyJuYW1lIjoid29ybGRIZWxsbyIsImlkIjoxMTQ1MTQsImlhdCI6MTU5NzM5Nzk0MSwiZXhwIjoxNTk3NjU3MTQxfQ

第三部分
otN7LikyB1mmknnBXL0mVrdOSFmID-dCORD5x4R3voM

token的第一和第二部分,都是base64编码的,这意味着他们是明文的,可以被解码的,下面给出各个部分的解码结果

第一部分:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
解码结果:
{"alg":"HS256","typ":"JWT"}

第二部分:
eyJuYW1lIjoid29ybGRIZWxsbyIsImlkIjoxMTQ1MTQsImlhdCI6MTU5NzM5Nzk0MSwiZXhwIjoxNTk3NjU3MTQxfQ
解码结果:
{"name":"worldHello","id":114514,"iat":1597397941,"exp":1597657141}

看到json格式的数据,想必都懂了,为啥叫json web token。

其中,第一部分声明了使用的算法,和token的类型,即为SHA256加密算法的JWT。

第二部分则是一些服务要用到的用户信息,这部分是服务器自定义添加的,比如用户登录的用户名和昵称,用户的余额等。在上诉例子中,我们添加nameid字段。值得注意的时,iat和exp字段表示签发时间和过期时间,token验证用。

第三部分是前两部分base64编码串,加上一个密钥,使用SHA256算法加密的结果(使用的算法在第一部分声明,即HS256)。值得注意的是,这个密钥只有服务器有,所以保证token都是服务器签发的。

具体的加密方式如下:

  1. 获取前两部分的base64加密字符串 s,即:(注意.号分割)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid29ybGRIZWxsbyIsImlkIjoxMTQ1MTQsImlhdCI6MTU5NzM5Nzk0MSwiZXhwIjoxNTk3NjU3MTQxfQ
  1. 将 s 串和一个密钥一起,利用HS256算法加密,形成第三部分。

因为整合了前两部分信息,服务器验证token时,利用前两部分+密钥,再次产生第三部分,然后和用户提交的第三部分比对,从而验证。

node中使用JWT

在node.js中使用JWT,我们直接用别人造好的轮子就好了,不必自己重复造轮子了。。

安装jsonwebtoken包

使用node的包管理工具npm可以快速安装

npm install jsonwebtoken

如果在linux下,记得加sudo再安装。如果报错,那么尝试使用npm link命令

npm link jsonwebtoken

签发token

签发token,我们需要指定两个信息:

  1. token第二部分中附带的用户信息
  2. 加密使用的密钥(字符串)

使用如下的jwt.sign函数,我们可以很快签发一个token,我们指定两个用户信息,即nameid,然后我们返回这个token。token的有效期是3天,当然你也可以指定 1000 表示有效期为1000毫秒。

var express = require('express');
var app = express();

var jwt = require('jsonwebtoken');

app.post('/', function(req, res, next) {
    // 信息部分
    var content = {
        "name": "worldHello",
        "id": 114514
    };
    // 密钥
    var key = "hello_world";
    var token = jwt.sign(content, key, {expiresIn:"3 days"});
    res.end(token);
});

app.listen(8888);

postman验证结果
JWT身份验证原理简单讲解与nodejs简单实现_第1张图片

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoid29ybGRIZWxsbyIsImlkIjoxMTQ1MTQsImlhdCI6MTU5NzQwMDc1OSwiZXhwIjoxNTk3NjU5OTU5fQ.0DFAZtFpN28PbE2wbSzyMv8rwHvl6T5QSGjK3brX_bI

可以查看base64的解码结果
JWT身份验证原理简单讲解与nodejs简单实现_第2张图片

验证token

使用 jwt.verify函数以验证token是否正确,我们传入token和分发token时的密钥(两个密钥须一致),回调函数就会处理

回调返回decode对象,这个对象是token【第二部分】的json字符串转过来的。我们可以读取用户token中的信息,并且回显:

注:这里使用 body-parser 包来进行POST请求参数的获取

var express = require('express');
var app = express();
var bodyParser = require('body-parser');
app.use(bodyParser.urlencoded({ extended: false }));	// 解析POST
app.use(bodyParser.json());								// 变成json对象

var jwt = require('jsonwebtoken');

app.post('/', function(req, res, next) {
    var token = req.body["token"];  // 获取token
    var key = "hello_world";        // 使用同样的密钥
    jwt.verify(token, key, function(err, decode) {
        // 如果token失效直接返回
        if(err) {
            res.end(JSON.stringify({
                "state": -111,
                "message": "token校验失败。信息: " + err.message
            }));
            return;
        }
        // 验证成功 返回用户名字
        res.end(JSON.stringify({
            "state": 1234,
            "message": decode.name
        }));
    });
});

app.listen(8888);

我们填入刚刚的token,尝试访问验证接口,如果正确,那么我们会看到我们token中保存的信息,即name字段:
JWT身份验证原理简单讲解与nodejs简单实现_第3张图片
如果我们填写错误的token,那么会被识别出来,比如我们篡改token的信息:

JWT身份验证原理简单讲解与nodejs简单实现_第4张图片
JWT身份验证原理简单讲解与nodejs简单实现_第5张图片

你可能感兴趣的:(nodejs,杂记,nodejs,jwt)