千家信息网

JWT如何在nodejs中使用

发表于:2025-11-06 作者:千家信息网编辑
千家信息网最后更新 2025年11月06日,这篇文章主要介绍"JWT如何在nodejs中使用"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"JWT如何在nodejs中使用"文章能帮助大家解决问题。什么是J
千家信息网最后更新 2025年11月06日JWT如何在nodejs中使用

这篇文章主要介绍"JWT如何在nodejs中使用"的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇"JWT如何在nodejs中使用"文章能帮助大家解决问题。

什么是JWT

JWT也就是JSON Web Token的缩写,也就是为了在网络应用环境中一种认证解决方案,在传统的认证机制中,无非是一下几个步骤:

1. 用户将账号密码发送到服务器;2. 服务器通过验证账号密码后,会在当前session中保存一些用户相关的信息,用户角色或者过期时间等等;3. 服务器给用户一个session_id, 写入用户的Cookie或者客户端自行保存在本地;4. 用户每次请求服务,都需要带上这个session_id,或许会通过Cookie,或者其他的方式;5. 服务器接收到后,回去数据库查询当前的session_id,校验该用户是否有权限;

这种模式有一种优势在于,服务器随时可以终止用户的权限,可以去数据库修改或者删除当前用户的session信息。但是也有一点不好的,就是如果是服务器集群的话,所有的机器就需要共享这些session信息,确保每台服务器都能够获取到相同的session存储信息。虽然可以解决这些问题,但是工程量巨大。

JWT方案的优势呢,就是不保存这些信息,token数据保存在客户端,每次接受请求时,只需要校验就好。

JWT的原理

简单说一下JWT的原理,其实就是客户端发送请求认证的时候,服务器在认证用户之后,会生成一个JSON对象,大概包括"你是谁,你是干嘛的等等,到期时间"这些信息,重要的是一定要有到期时间;大致格式为:

{    username: "贼烦字符串er",    role: "世代码农",    endTime: "2022年5月20日"}

但是不会用这么肤浅的方式传给你,它会通过制定的签名算法和你提交的payload的一些信息进行可逆的签名算法进行签名后传输,大致的格式我用一张图片表示:

由图片可以看出,返回的信息大致分为三部分,左侧为签名之后的结果,也就是返回给客户端的结果,右侧也是就Decoded的源码了,三部分由"点"隔开,分别由红、紫、青三种颜色一一对应:

  • 第一个红色部分是Header,Header中主要是指定了的方式,图中的签名算法(默认HS256)就是带有 SHA-256 的 HMAC 是一种对称算法, 双方之间仅共享一个密钥,typ字段标识为JWT类型;

  • 第二个紫色部分payload,就是一个JSON对象,也就是实际要传输的数据,官方有七个字段可以使用:

    • iss (issuer):签发人

    • exp (expiration time):过期时间

    • sub (subject):主题

    • aud (audience):受众

    • nbf (Not Before):生效时间

    • iat (Issued At):签发时间

    • jti (JWT ID):编号

除了这些字段,你还可以搞一些自定义的字段,由于JWT默认是不加密的,所以在使用的时候尽量注意不要使用一些敏感数据。

  • 第三部分就是Signature签名,这一部分,是由你自己指定且只有服务器存在的秘钥,然后使用头部指定的算法通过下面的签名方法进行签名。

JWT的简单使用

下面我们来感受一下具体的使用:

第一步:我们需要搭建一个nodejs的项目;通过npm init -y初始化一个项目;之后我们需要安装依赖,分别按状expressjsonwebtokennodemon三个依赖:

$ npm i express jsonwebtoken nodemon

之后在package.json中的scripts字段中添加nodemon app.js命令:

"scripts": {    "start": "nodemon app.js"},

第二步:初始化一下node应用,在根目录下创建app.js文件;

// app.jsconst express = require("express");const app = express();app.use(express.json());app.listen(3000, () => {  console.log(3000 + " listening..."); // 监听3000端口});

第三步:引入jsonwebtoken依赖,并且创建接口和服务器的私钥;

// app.js//...const jwt = require("jsonwebtoken");const jwtKey = "~!@#$%^&*()+,";// ...

这里面的jwtKey是我们自定义保存仅限保存在服务器中的私钥,之后我们开始写一个 /login 接口,用来登录,并且创建本地的模拟数据库用来校验,并通过jwt.sign方法进行校验签名:

// app.jsconst database = {  username: "username",  password: "password",};app.post("/login", (req, res) => {  const { username, password } = req.body;  if (username === database.username && password === database.password) {    jwt.sign(      {        username,      },      jwtKey,      {        expiresIn: "30S",      },      (_, token) => {        res.json({          username,          message: "登陆成功",          token,        });      }    );  }});

上面代码中我们创建了database变量来模拟创建了本地的账号密码数据库,用来校验登陆;接下来建立了一个/loginpost接口,在校验账号密码完全匹配之后,我们通过jsonwebtoken包导入的jwt对象下的人sign方法进行签名,这个方法有三种接口签名:

export function sign(    payload: string | Buffer | object,    secretOrPrivateKey: Secret,    options?: SignOptions,): string;export function sign(    payload: string | Buffer | object,    secretOrPrivateKey: Secret,    callback: SignCallback,): void;export function sign(    payload: string | Buffer | object,    secretOrPrivateKey: Secret,    options: SignOptions,    callback: SignCallback,): void;

这里用到了函数重载的方式实现接口,我们这里将实现最后一个接口签名,第一个参数可以是一个自定义的对象类型,也可以是一个Buffer类型,还可以直接是一个string类型,我们的源码使用了object类型,自定义了一些字段,因为jwt在进行签名是也会对这些数据一并进行签名,但是值得注意的是,这里尽量不要使用敏感数据,因为JWT默认是不加密的,它的核心就是签名,保证数据未被篡改,而检查签名的过程就叫做验证

当然你也可以对原始Token进行加密后传输;

第二个参数:是我们保存在服务器用来签名的秘钥,通常在客户端-服务端模式中,JWS 使用 JWA 提供的 HS256 算法加上一个密钥即可,这种方式严格依赖密钥,但在分布式场景,可能多个服务都需要验证JWT,若要在每个服务里面都保存密钥,那么安全性将会大打折扣,要知道,密钥一旦泄露,任何人都可以随意伪造JWT。

第三个参数:是签名的选项SignOptions,接口的签名:

export interface SignOptions {    algorithm?: Algorithm | undefined;    keyid?: string | undefined;    expiresIn?: string | number | undefined;    /** expressed in seconds or a string describing a time span [zeit/ms](https://github.com/zeit/ms.js).  Eg: 60, "2 days", "10h", "7d" */    notBefore?: string | number | undefined;    audience?: string | string[] | undefined;    subject?: string | undefined;    issuer?: string | undefined;    jwtid?: string | undefined;    mutatePayload?: boolean | undefined;    noTimestamp?: boolean | undefined;    header?: JwtHeader | undefined;    encoding?: string | undefined;}

这里我们用的是expiresIn字段,指定了时效时间,使用方法参考这个文档;

第四个参数是一个回调,回调的第二个参数就是我们通过签名生成的token,最后将这个token返回给前端,以便存储到前端本地每次请求是带上到服务端进行验证。

接下来,我们来验证一下这个接口: 我是在vscode安装的REST Client插件,之后在根目录创建一个request.http的文件,文件内写上请求的信息:

POST http://localhost:3000/logincontent-type: application/json{  "username": "username",  "password": "password"}

之后在命令行执行npm run start命令启动服务,之后在requset.http文件上方点击Send Request按钮,发送请求:

请求成功后,会看到这样的响应报文:

token字段就是我们JWT生成的token;

下面来验证一下这个token是否有效,我们在写一个登录过后的接口:

app.get("/afterlogin", (req, res) => {  const { headers } = req;    const token = headers["authorization"].split(" ")[1];  // 将token放在header的authorization字段中  jwt.verify(token, jwtKey, (err, payload) => {    if (err) return res.sendStatus(403);    res.json({ message: "认证成功", payload });  });});

这段代码中,通过获取请求头中的authorization字段中的token进行获取之前通过JWT生成的token。 之后通过调用jwt.verify校验方法校验这个token是否有效,这个方法分别有三个参数:

// 有四个接口签名,可以自行查文档export function verify(    token: string,    // 需要检验的token    secretOrPublicKey: Secret | GetPublicKeyOrSecret,    // 定义在服务器的签名秘钥    callback?: VerifyCallback,    // 获取校验信息结果的回调): void;

接下来我们把刚才响应的token复制到请求头中:

###GET http://localhost:3000/afterloginauthorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6InVzZXJuYW1lIiwiaWF0IjoxNjUyNzg5NzA3LCJleHAiOjE2NTI3ODk3Mzd9.s9fk3YLhxTUcpUgCfIK4xQN58Hk_XEP5y9GM9A8jBbY

前面的Bearer认证, 是http协议中的标准认证方式

同样点击Send Request当看到下面图片的响应,就意味着响应成功:

其实以上就是JWT的一些简单的用法,接下来再说一下JWT本身存在的优缺点.

JWT的不足

  • JWT占用的存储空间其实并不小,如果我们需要签名做过多的信息,那么token很可能会超出cookie的长度限制,例如对比一下这两张图片:

很明显,随着payload的信息量增大,token的长度也会增加;

  • 安全性,其实如果token的占用空间过大,Cookie最大存储空间只有4kb前端可以存储在localStorage之类的本地存储,但是会带来一个问题,如果不是放在cookie的话,安全性就会大打折扣,就会有通过js脚本获取到的风险,就意味着任何hacker都可以拿着它做任何事情;

  • 不灵活的时效性,其实JWT的某方面意义在于用户token不需要持久化存储,而是采用服务器校验的方式对token进行有效校验,刚才看到了,签名也是把到期时间一并签名的,如果改变到期时间token就会被篡改,由于没有存储和手动更改时效的方法,所以很难立刻将这个token删掉,如果用户重复登陆两次,生成两个token,那么原则上两个token都是有效的;

关于"JWT如何在nodejs中使用"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注行业资讯频道,小编每天都会为大家更新不同的知识点。

服务 服务器 信息 用户 字段 就是 接口 数据 方法 时间 存储 方式 认证 参数 算法 验证 客户 密钥 类型 部分 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 lol服务器特色巨龙之巢 集结号服务器 网络技术服务部工资 航海王强者之路服务器人物没了 数据库主码可以为空么 社会工程学数据库搭建 工业网络技术与智能制造 平度手机软件开发系统 上海网络安全公司股票 企业服务器租用多少钱一月 山西app软件开发高品质的选择 进口软件开发工具报价 我的世界服务器一直生成世界 服务器卡死 学校网络安全工作活动总结 学计算机网络技术的怎么就业 工联数据库是什么部门 打开服务器出现连接数据库失败 中国软件开发策朋信息公司 物联网软件开发心得 联想存储服务器默认密码 有线电视网络服务器怎么设置 exp备份数据库时表行显示 三种基本类型数据库 企业服务器租用多少钱一月 如何购买软件开发笔记本 一刀传世服务器角色满了怎么办 上海跨品种套利软件开发 棒棒糖 软件开发工具包 研发科技公司是互联网吗
0