在现代 Web 应用中,认证是必不可少的一环。JSON Web Token(JWT)是一种基于 JSON 的轻量级身份验证和授权机制,被广泛应用于前后端分离的 Web 应用中。Hapi 是一个 Node.js 的 Web 框架,提供了可扩展、可配置和可测试的接口,使得使用 JWT 认证在 Hapi 中变得异常简单。
本文将介绍如何在 Hapi 中使用 JWT 认证。我们将通过一个示例应用程序来演示如何实现 JWT 认证,以及如何在 Hapi 中进行配置和使用。
什么是 JWT?
JWT 是一个开放标准(RFC 7519),它定义了一种紧凑且自包含的方式,用于在各方之间作为 JSON 对象安全地传输信息。JWT 可以使用 HMAC 算法或 RSA 公钥/私钥对进行签名,以验证发送方是否为其声称的发送方,并保证消息的完整性。
JWT 由三部分组成:头部、载荷和签名。头部包含了令牌的类型和所使用的算法信息。载荷包含了需要传输的信息,例如用户 ID、角色等。签名是由头部和载荷组成的字符串进行签名生成的,用于验证令牌的完整性。
在 Hapi 中实现 JWT 认证
在 Hapi 中使用 JWT 认证,需要安装 hapi-auth-jwt2
插件。该插件提供了一组策略和路由配置,用于实现 JWT 认证。安装该插件的命令如下:
npm install hapi-auth-jwt2
安装完成后,在 Hapi 的配置文件中注册该插件:
-- -------------------- ---- ------- ----- ---- - ---------------------- ----- --- - --------------------- ----- ------- - -------------------------- ----- ---- - ----- -- -- - ----- ------ - ------------- ----- ----- ----- ------------ --- ----- ----------------- ---- -------- --- -- --- - -------
接下来,我们需要定义一个 JWT 策略,以及相应的路由配置。在 Hapi 中,可以使用 server.auth.strategy()
方法定义策略。以下是一个简单的 JWT 策略定义:
server.auth.strategy('jwt', 'jwt', { key: 'my_secret_key', // 签名密钥 validate: async (decoded, request, h) => { // 用户验证逻辑 return { isValid: true }; }, verifyOptions: { algorithms: ['HS256'] }, // 签名算法 });
在上面的代码中,我们定义了一个名为 jwt
的策略,使用了 jwt
插件。其中,key
参数为签名密钥,validate
参数为用户验证函数,verifyOptions
参数为签名算法。用户验证函数的返回值应该是一个包含 isValid
属性的对象,用于表示用户是否验证成功。
接下来,我们需要定义需要进行 JWT 认证的路由。在 Hapi 中,可以使用 auth
参数指定需要使用的策略。以下是一个简单的 JWT 认证路由配置:
-- -------------------- ---- ------- -------------- ------- ------ ----- ------------- -------- --------- -- -- - -- ------ ------ ------- -------- -- -------- - ----- ------ -- -- --- ------ -- ---
在上面的代码中,我们定义了一个名为 /api/users
的路由,使用了 jwt
策略进行认证。当用户访问该路由时,如果未提供有效的 JWT,则返回 401 错误。
示例应用程序
为了更好地理解 JWT 认证在 Hapi 中的实现方法,我们将通过一个示例应用程序来演示如何实现 JWT 认证。该应用程序包含以下功能:
- 用户注册和登录
- JWT 认证
- 获取用户信息
准备工作
首先,我们需要创建一个新的 Hapi 项目,并安装所需的依赖:
mkdir hapi-jwt-example cd hapi-jwt-example npm init -y npm install @hapi/hapi @hapi/joi bcrypt hapi-auth-jwt2 mongoose
在上面的命令中,我们安装了 Hapi、Joi、bcrypt、hapi-auth-jwt2 和 Mongoose 库。其中,Joi 用于验证用户输入数据的有效性,bcrypt 用于密码加密,Mongoose 用于与 MongoDB 数据库进行交互。
接下来,我们需要创建一个 MongoDB 数据库,并创建一个名为 users
的集合。
用户注册和登录
在开始实现 JWT 认证之前,我们需要实现用户注册和登录功能。以下是一个简单的用户模型定义:
-- -------------------- ---- ------- ----- -------- - -------------------- ----- ---------- - --- ----------------- ------ - ----- ------- --------- ----- ------- ----- ---------- ----- -- --------- - ----- ------- --------- ----- -- ----- - ----- ------- --------- ----- -- ----- - ----- ------- ----- -------- --------- -------- ------- -- --- -------------- - ---------------------- ------------
在上面的代码中,我们定义了一个名为 User
的模型,包含了用户的电子邮件、密码、姓名和角色信息。在用户注册时,我们需要将密码进行加密。以下是一个简单的用户注册路由定义:
-- -------------------- ---- ------- ----- --- - --------------------- ----- ------ - ------------------ ----- ---- - ------------------------- -- ------ -------------- ------- ------- ----- ---------------- -------- ----- --------- -- -- - ----- - ------ --------- ---- - - ---------------- -- ------------ ----- ------ - ------------ ------ -------------------------------- --------- ------------------------------- ----- ------------------------ --- ----- - ----- - - ----------------- ------ --------- ---- --- -- ------- - ----- ----------------------------------------------- - -- ---------- ----- ---- - ----- -------------- ----- --- -- ------ - ----- ---------------- ------- ------------------- - -- ----- ----- -------------- - ----- --------------------- ---- ----- ------- - --- ------ ------ --------- --------------- ----- --- ----- --------------- ------ ---------------- ---------- ------------------------- -- ---
在上面的代码中,我们定义了一个名为 /api/register
的路由,用于注册新用户。在用户注册时,我们首先使用 Joi 库验证用户输入数据的有效性。然后,我们检查用户是否已经注册。最后,我们将密码进行加密,创建新用户,并将其保存到数据库中。
用户登录功能与用户注册类似。以下是一个简单的用户登录路由定义:
-- -------------------- ---- ------- -- ------ -------------- ------- ------- ----- ------------- -------- ----- --------- -- -- - ----- - ------ -------- - - ---------------- -- ------------ ----- ------ - ------------ ------ -------------------------------- --------- ------------------------ --- ----- - ----- - - ----------------- ------ -------- --- -- ------- - ----- ----------------------------------------------- - -- -------- ----- ---- - ----- -------------- ----- --- -- ------- - ----- ------------------- ----- -- --------------------- - -- ------ ----- --------------- - ----- ------------------------ --------------- -- ------------------ - ----- ------------------- ----- -- --------------------- - -- -- --- ----- ----- - ----------------- ---- --------- ----- ---------- ----- ---------- --- ------ - ----- -- -- ---
在上面的代码中,我们定义了一个名为 /api/login
的路由,用于用户登录。在用户登录时,我们首先使用 Joi 库验证用户输入数据的有效性。然后,我们检查用户是否存在,并验证用户密码。最后,我们使用 server.jwt.sign()
方法创建 JWT,并将其返回给客户端。
在用户登录成功后,客户端应该将 JWT 存储在本地存储或会话存储中。在每次向服务器发送请求时,客户端应该将 JWT 添加到请求头中。以下是一个简单的客户端请求示例:
const token = localStorage.getItem('token'); axios.get('/api/users', { headers: { Authorization: `Bearer ${token}` } });
JWT 认证
现在,我们已经实现了用户注册和登录功能。接下来,我们需要使用 JWT 认证保护需要授权访问的路由。在 Hapi 中,我们可以使用 server.auth.strategy()
方法定义 JWT 策略。以下是一个简单的 JWT 策略定义:
-- -------------------- ---- ------- --------------------------- ------ - ---- ---------------- -- ---- --------- ----- --------- -------- -- -- - -- -------- ----- ---- - ----- --------------------------- -- ------- - ------ - -------- ----- -- - -- ------ ------ - -------- ----- ------------ ---- -- -- -------------- - ----------- --------- -- -- ---- ---
在上面的代码中,我们定义了一个名为 jwt
的策略,使用了 jwt
插件。其中,key
参数为签名密钥,validate
参数为用户验证函数,verifyOptions
参数为签名算法。在用户验证函数中,我们使用 JWT 中的 sub
字段查找用户,并将其返回给客户端。
接下来,我们需要使用 auth
参数指定需要使用的策略。以下是一个简单的受保护路由定义:
-- -------------------- ---- ------- -- ------ -------------- ------- ------ ----- ------------- -------- --------- -- -- - ----- ---- - ------------------------- ------ ------- --------------- -- -------- - ----- ------ -- -- --- ------ -- ---
在上面的代码中,我们定义了一个名为 /api/users
的受保护路由,使用了 jwt
策略进行认证。当用户访问该路由时,如果未提供有效的 JWT,则返回 401 错误。如果 JWT 有效,则返回用户信息。
完整示例代码
以下是完整的示例代码:
-- -------------------- ---- ------- ----- ---- - ---------------------- ----- --- - --------------------- ----- ------ - ------------------ ----- -------- - -------------------- ----- --- - --------------------- ----- ------- - -------------------------- ----- ---- - ------------------------- ----- ---- - ----- -- -- - ----- -------------------------------------------------------- - ---------------- ----- ------------------- ----- --------------- ----- --- ----- ------ - ------------- ----- ----- ----- ------------ --- ----- ----------------- ---- -------- --- -- ------ -------------- ------- ------- ----- ---------------- -------- ----- --------- -- -- - ----- - ------ --------- ---- - - ---------------- -- ------------ ----- ------ - ------------ ------ -------------------------------- --------- ------------------------------- ----- ------------------------ --- ----- - ----- - - ----------------- ------ --------- ---- --- -- ------- - ----- ----------------------------------------------- - -- ---------- ----- ---- - ----- -------------- ----- --- -- ------ - ----- ---------------- ------- ------------------- - -- ----- ----- -------------- - ----- --------------------- ---- ----- ------- - --- ------ ------ --------- --------------- ----- --- ----- --------------- ------ ---------------- ---------- ------------------------- -- --- -- ------ -------------- ------- ------- ----- ------------- -------- ----- --------- -- -- - ----- - ------ -------- - - ---------------- -- ------------ ----- ------ - ------------ ------ -------------------------------- --------- ------------------------ --- ----- - ----- - - ----------------- ------ -------- --- -- ------- - ----- ----------------------------------------------- - -- -------- ----- ---- - ----- -------------- ----- --- -- ------- - ----- ------------------- ----- -- --------------------- - -- ------ ----- --------------- - ----- ------------------------ --------------- -- ------------------ - ----- ------------------- ----- -- --------------------- - -- -- --- ----- ----- - ----------------- ---- --------- ----- ---------- ----- ---------- --- ------ - ----- -- -- --- -- ------ -------------- ------- ------ ----- ------------- -------- --------- -- -- - ----- ---- - ------------------------- ------ ------- --------------- -- -------- - ----- ------ -- -- --- ------ -- --- -- --- ---- --------------------------- ------ - ---- ---------------- -- ---- --------- ----- --------- -------- -- -- - -- -------- ----- ---- - ----- --------------------------- -- ------- - ------ - -------- ----- -- - -- ------ ------ - -------- ----- ------------ ---- -- -- -------------- - ----------- --------- -- -- ---- --- ----- --------------- ------------------- ------- -- ---- ----------------- -- -------------------------------- ----- -- - ----------------- ---------------- --- -------
总结
在本文中,我们介绍了如何在 Hapi 中使用 JWT 认证。我们通过一个示例应用程序演示了如何实现用户注册和登录功能,以及如何使用 JWT 认证保护需要授权访问的路由。JWT 认证是一种非常流行的身份验证和授权机制,在前后端分离的 Web 应用中被广泛应用。Hapi 是一个灵活、可扩展和可测试的 Node.js Web 框架,使得使用 JWT 认证在 Hapi 中变得异常简单。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/650d3f3395b1f8cacd6f4d63