koa-jwt 全面解析,安检利器!

本文介绍koa-jwt中间件的使用,包括JWT概念、token生成与验证过程。通过代码示例,展示如何设置登录验证,以及如何保护路由仅允许已认证用户访问。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

学习 Koa 不易,今天学习到了 koa-jwt 这个登陆验证必不可少的中间件。本文会说明jwt是什么、token怎么来的、如何验证token。
一反常态,先上代码!(本代码由 koa-generater 生成,安装 koa-jwt, jsonwebtoken 两个 npm 包 )

文件名及源代码:

文件名: app.js

红色框:jwt 相关的代码
蓝色框:为了完成demo,在原有脚手架中做的调整。

文件名: routes/index.js

这里简单的模仿一个 login 请求,返回一个 token。

文件名: routes/users.js

/users 以下的路由需通过 jwt 验证才能访问


文件名: auth.js


思路及说明

1.我们在浏览器输入 localhost:3000/login 获取 token。一下大串都是token,分为3部分,用 '.' 分隔;

2.这里用 postman 去访问 localhost:3000/users/info 模拟访问用户数据。要在 header中加入 authorization, 注意:authorization的值的格式;

3.当输入 users 路由的时候 koa-jwt 不去验证 token 的正确性,仅仅去验证header中是否有 authorization 并且值为 'Bearer token',然后再根据配置中 isRevoked 的函数去进行验证。isRevoked 返回 true 表明 token 不正确,false 表示 token 正确。
4.在验证中,使用 jsonwebtoken.verify 去验证 token 是否正确,并返回。

API 解析:

Koa-jwt:这个函数还是截图看得清楚

1.secret: 可以理解为一个加密因子,在生成 token 的时候用这个因子,验证 token 的时候也用同一个。Serect 可以是数组,当secret是一个数组时,在验证 token 时任何一个 因子通过验证,token就合法有效。
2.passthrough: 当为true时,即使在 header 中没有 authorization 也会通过这个 中间件(仅仅通过中间件的验证,没有通过 jsonwebtoken.verify)
3.isRevoked:需要一个函数来验证token的对错。这个函数有3个参数:ctx, decodedToken, token。其中 token 可以直接被验证: jsonwebtoken.verify(token)

Jsonwebtoken: 这个才是主角!

jsonwebtoken.sign(payload, secretOrPrivateKey, [options, callback]) 生成 token复制代码

1.payload 是需要被加密的数据(我的理解 jwt其实就是加密解密和验证的过程)。在payload里有三个key很特别:iat(issued at)、exp(expiresIn)、nbf(notBefore),这几个参数推荐写在 options 中,不建议写在 payload 里;
2.secretOrPrivateKey 可以是字符串,也可以是对成加密的 key,或者非对称加密的私有key;
3.options 这里可以选择的参数就好多了,algorithms:加密算法,默认是HS256,expriesIn: token有效持续时间,notBefore: token在什么时候失效,更多参数请参考官网;
4.返回一个token。


jwt.verify(token, secretOrPublicKey, [options, callback]) 对token的验证复制代码

1.token : 当然是用 sign 函数生成的token啦;
2.secretOrPublicKey:与生成 token 的加密因子相互对应,要么是相同的字符串和对称加密的key,或者是非对称加密的公有key;
3.options: 与 sign 相互照应且要一致。audience,issuer,jwtid等。
4.正确的时候返回 payload,错误的时候throw 一个 err,里面包含了错误的message,根据message判断错误类型。

文档这里有个坑:
expiredIn: 默认单位是 秒!!! 以下是铁证啊( jsonwebtoken/verify.js ,这里是用秒做的对比,千万别以为是毫秒


Tips: 通常情况下,我们也会在cookie里写一份token,这样每个请求都可以通过token验证,此时可以忽略 header中的 autherization(passthrough: true


### Koa-JWT 配置参数说明及使用方法 Koa-JWT 是一个用于 Koa 应用程序的身份验证中间件,基于 JSON Web Token (JWT) 技术。以下是关于 `koa-jwt` 的配置参数及其使用方法的详细介绍。 #### 1. **核心配置参数** - **secret**: 定义签名或验证 JWT 所需的秘密密钥或私钥。它可以是一个字符串、缓冲区或键对象。如果未提供,则需要通过上下文 (`ctx`) 动态传递密钥[^2]。 ```javascript const jwt = require('koa-jwt'); app.use(jwt({ secret: 'your-secret-key' })); ``` - **key**: 设置解析后的令牌存储位置,默认情况下会将解析后的数据存放在 `ctx.state.user` 中。可以通过自定义该选项更改存储路径[^1]。 ```javascript app.use(jwt({ secret: 'your-secret-key', key: 'customKey' })); ``` - **passthrough**: 如果设置为 `true`,即使请求头中缺少有效的 JWT 或者验证失败也不会抛出错误,而是允许继续执行后续路由逻辑[^3]。 ```javascript app.use(jwt({ secret: 'your-secret-key', passthrough: true })); ``` - **audience**, **issuer**, 和其他可选字段: 提供额外的安全约束条件,比如指定受众(audience)和签发方(issuer)。这些通常作为选项的一部分传入以增强安全性[^2]。 ```javascript app.use(jwt({ secret: 'your-secret-key', audience: 'example-audience', issuer: 'example-issuer' })); ``` #### 2. **高级功能** - **除非特定路径不需要认证**: 使用 `.unless()` 方法排除某些无需身份验证的 URL 路径,例如登录页面或注册接口[^3]。 ```javascript const unlessPaths = ['/user/login', '/public/resource']; app.use(jwt({ secret: 'your-secret-key' }).unless({ path: unlessPaths })); ``` - **动态秘钥支持**: 当不同用户可能拥有不同的签名密钥时,可以利用回调函数动态生成秘密密钥[^4]。 ```javascript function dynamicSecret(ctx) { return ctx.headers['dynamic-secret'] || 'default-secret'; } app.use(jwt({ secret: dynamicSecret })); ``` - **Token 解析与校验流程**: 在实际应用过程中,`koa-jwt` 将自动尝试从 HTTP 请求头部提取 Bearer Token 并完成解码操作。一旦成功解析并匹配给定的 `secret` 参数后,就会把载荷信息注入至当前请求状态下的指定变量名下(默认为 `ctx.state.user`)[^5]。 #### 示例代码片段 下面展示了一个完整的集成例子: ```javascript const Koa = require('koa'); const Router = require('@koa/router'); const jwt = require('koa-jwt'); // 创建实例化服务端框架 const app = new Koa(); const router = new Router(); // 秘钥设定以及例外情况处理 app.use( jwt({ secret: 'my-strong-secret', key: 'authUser', // 自定义保存已验证用户的属性名称 passthrough: false, }) .unless({ path: [/^\/login/] }) // 登录接口免受保护 ); router.post('/login', async (ctx) => { const { username, password } = ctx.request.body; if (username === 'admin' && password === 'password') { const token = jwt.sign({ id: 1 }, 'my-strong-secret'); // 签署新的访问令牌 ctx.body = { success: true, token }; } else { ctx.status = 401; ctx.body = { error: 'Invalid credentials.' }; } }); router.get('/protected', async (ctx) => { const user = ctx.state.authUser; // 获取经过授权的信息 ctx.body = { message: `Welcome ${user.id}` }; }); app.use(router.routes()); app.listen(3000); console.log('Server running on port 3000...'); ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值