在现代 Web 开发中,鉴权(Authentication)和授权(Authorization)是不可或缺的一环。JWT (JSON Web Token) 是一种安全传递信息的方法,可以用于鉴权。Koa2 是一个 Web 开发框架,可以用于服务器端开发。Koa2 中结合 JWT 实现鉴权方案,能够有效保证用户数据的安全性。
JWT 的基本原理
JWT 是由头部(Header)、载荷(Payload)和签名(Signature)三个部分组成的字符串,其示例格式如下:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
其中:
- Header:由两部分组成,第一部分是 token 类型,如 JWT,第二部分是所使用的加密算法,如 HMAC SHA256 或 RSA。
- Payload:也称为 claims,是 key-value 的形式,其中包含了需要传递的信息,如用户 id、过期时间等。关键信息不能放在 Payload 中,如密码等。
- Signature:使用 Base64Url 编码后的签名,它由 Header、Payload 和 secret(密钥)三部分组成,用于校验消息的完整性。
JWT 的基本原理是:
- 客户端向服务器请求资源或者进行操作时,将 JWT 放在请求的 header 中,以 Authorization 为 key,Bearer + JWT 字符串为 value。
- 服务器收到请求后,解析头部和载荷,根据头部中声明的算法和密钥,利用加密算法对载荷进行签名。签名后的 token 会在 Response Header 中返回给客户端。
- 客户端收到 token 后,保存到本地,以后的每个请求都在 Header 中添加该 token。服务器收到请求后,对 Header 中的 token 进行解析,校验 token 的合法性和完整性,判断该用户是否有权进行所请求的操作。
Koa2 的基本用法
Koa2 是一个轻量级的 Web 开发框架,它可以让我们使用更少的代码进行服务器端开发。下面是基本的用法:
const Koa = require('koa'); const app = new Koa(); app.use(async ctx => { ctx.body = 'Hello World'; }); app.listen(3000);
这段代码创建了一个 Koa2 应用程序,并通过 app.use 方法添加了一个中间件函数。当请求到达服务器时,该中间件函数会被调用并返回响应内容,代码输出 "Hello World" 到响应中。
实现 JWT 鉴权方案
在 Koa2 中实现 JWT 鉴权方案,需要使用以下两个中间件:
- koa-jwt:用于解析 token 和验证签名的中间件。
- koa-bodyparser:用于解析 POST 请求中的请求体,以便在后续的中间件中使用请求体中的参数。
安装 koa-jwt 和 koa-bodyparser
在终端中运行以下命令安装两个依赖:
npm install koa-jwt koa-bodyparser
创建用户登录接口
我们首先需要创建一个用户登录接口,接收用户名和密码,然后验证用户名和密码是否匹配,如果验证通过,则创建一个 JWT 并将其返回给客户端。
-- -------------------- ---- ------- ----- ------ - ---------------------- ----- --- - ------------------------ ----- ---------- - -------------------------- ----- ------ - --- --------- ----- ------ - --------- -- -- --------------------- ------------- ----- ----- ----- -- - ----- - --------- -------- - - ----------------- -- ------------ ----- ---- - - --- -- --------- ------ -- -- ------ -- -------- --- ------------- -- -------- --- --------- - -------------- ------------ - ----- ----- - ---------- --- ------- -- ------- - ---------- ---- --- -------- - - ----- -- ----- ------- ---
这段代码创建了一个 /login 接口,首先解析 POST 请求中的请求体并取出用户名和密码。然后根据用户名查找用户,如果未找到,则返回 401 状态码和错误信息;如果密码验证不通过,也返回 401 状态码和错误信息。如果验证通过,则创建一个 JWT,并将其添加到响应体中返回给客户端。JWT 的有效期为 1 小时。
创建需要鉴权的接口
接下来,我们创建一个需要鉴权的接口,判断当前用户是否已登录,如果已登录则返回用户信息,否则返回 401 状态码和错误信息。
-- -------------------- ---- ------- ------------------- ----- ----- ----- -- - ----- ----- - -------------------------------- ------ --- - ----- ------- - ----------------- -------- -- ---------- - -------------- ------------- - -- ------------ ----- ---- - - --- ----------- --------- ------ -- -------- - - ---- -- - ----- ----- - -------------- ------------- - ----- ------- ---
这段代码创建了一个 /user 接口,读取请求头中的 Authorization 字段并取出 JWT。然后使用 jwt.verify 函数对 JWT 进行校验,如果校验通过,则说明用户已登录。此时可以根据 JWT 中的用户 id 查找数据库获取用户信息,并将用户信息返回给客户端。如果校验失败,则返回 401 状态码和错误信息。
添加全局异常处理
我们需要添加一个全局异常处理函数来拦截所有错误,并将错误信息返回给客户端。
app.use(async (ctx, next) => { try { await next(); } catch (err) { ctx.status = err.status || 500; ctx.body = { message: err.message }; } });
这段代码创建了一个全局异常处理中间件函数,它会在所有的请求中使用。当请求中发生错误时,该中间件函数会将错误信息返回给客户端。如果错误对象中有 status 属性,则使用该属性作为状态码;否则使用 500 作为状态码。
将路由挂载到应用
最后,我们将路由挂载到应用中,使应用可以监听所有 /login 和 /user 请求。
app.use(router.routes()).use(router.allowedMethods());
示例代码
下面是完整的代码示例:
-- -------------------- ---- ------- ----- --- - --------------- ----- ------ - ---------------------- ----- --- - ------------------------ ----- ---------- - -------------------------- ----- --- - --- ------ ----- ------ - --- --------- ----- ------ - --------- -- -- --------------------- ------------- ----- ----- ----- -- - ----- - --------- -------- - - ----------------- -- ------------ ----- ---- - - --- -- --------- ------ -- -- ------ -- -------- --- ------------- -- -------- --- --------- - -------------- ------------ - ----- ----- - ---------- --- ------- -- ------- - ---------- ---- --- -------- - - ----- -- ----- ------- --- ------------------- ----- ----- ----- -- - ----- ----- - -------------------------------- ------ --- - ----- ------- - ----------------- -------- -- ---------- - -------------- ------------- - -- ------------ ----- ---- - - --- ----------- --------- ------ -- -------- - - ---- -- - ----- ----- - -------------- ------------- - ----- ------- --- ------------- ----- ----- -- - --- - ----- ------- - ----- ----- - ---------- - ---------- -- ---- -------- - - -------- ----------- -- - --- ------------------------------------------------------ ---------------- -- -- - ---------------------- ---- ----- ---
总结
本篇文章介绍了如何在 Koa2 中使用 JWT 实现前后端分离的鉴权方案。该方案不仅能有效保障用户数据的安全性,而且具有良好的扩展性和可维护性,适合用于大型 Web 开发项目。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64547930968c7c53b085ce5c