基于 Hapi 的 JSON Web Token 认证实践

在现代 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 认证。安装该插件的命令如下:

--- ------- --------------

安装完成后,在 Hapi 的配置文件中注册该插件:

----- ---- - ----------------------
----- --- - ---------------------
----- ------- - --------------------------

----- ---- - ----- -- -- -
  ----- ------ - -------------
    ----- -----
    ----- ------------
  ---

  ----- -----------------
    ----
    --------
  ---

  -- ---
-

-------

接下来,我们需要定义一个 JWT 策略,以及相应的路由配置。在 Hapi 中,可以使用 server.auth.strategy() 方法定义策略。以下是一个简单的 JWT 策略定义:

--------------------------- ------ -
  ---- ---------------- -- ----
  --------- ----- --------- -------- -- -- -
    -- ------
    ------ - -------- ---- --
  --
  -------------- - ----------- --------- -- -- ----
---

在上面的代码中,我们定义了一个名为 jwt 的策略,使用了 jwt 插件。其中,key 参数为签名密钥,validate 参数为用户验证函数,verifyOptions 参数为签名算法。用户验证函数的返回值应该是一个包含 isValid 属性的对象,用于表示用户是否验证成功。

接下来,我们需要定义需要进行 JWT 认证的路由。在 Hapi 中,可以使用 auth 参数指定需要使用的策略。以下是一个简单的 JWT 认证路由配置:

--------------
  ------- ------
  ----- -------------
  -------- --------- -- -- -
    -- ------
    ------ ------- --------
  --
  -------- -
    ----- ------ -- -- --- ------
  --
---

在上面的代码中,我们定义了一个名为 /api/users 的路由,使用了 jwt 策略进行认证。当用户访问该路由时,如果未提供有效的 JWT,则返回 401 错误。

示例应用程序

为了更好地理解 JWT 认证在 Hapi 中的实现方法,我们将通过一个示例应用程序来演示如何实现 JWT 认证。该应用程序包含以下功能:

  • 用户注册和登录
  • JWT 认证
  • 获取用户信息

准备工作

首先,我们需要创建一个新的 Hapi 项目,并安装所需的依赖:

----- ----------------
-- ----------------
--- ---- --
--- ------- ---------- --------- ------ -------------- --------

在上面的命令中,我们安装了 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 添加到请求头中。以下是一个简单的客户端请求示例:

----- ----- - ------------------------------
----------------------- - -------- - -------------- ------- --------- - ---

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


猜你喜欢

  • Mongoose 聚合查询的使用技巧

    Mongoose 是一个优秀的 Node.js ORM 框架,它支持对 MongoDB 数据库进行操作。在 Mongoose 中,聚合查询是一种非常重要的查询方式,它可以对数据进行统计、分组、过滤等复...

    1 年前
  • 处理 Node.js 中的字符串的思考

    在 Node.js 中,字符串是最常用的数据类型之一。处理字符串是前端开发中的一个重要部分,因为它们是用于输入和输出的主要方式。在本文中,我们将探讨一些 Node.js 中处理字符串的方法,并提供一些...

    1 年前
  • 如何在 GraphQL 中处理批量写操作

    GraphQL 是一种新兴的 API 查询语言,它提供了一种更加灵活和高效的方式来请求和获取数据。在 GraphQL 中,通常使用 Query 和 Mutation 来进行数据的读取和写入操作。

    1 年前
  • 前端 - Vanilla Web Components 库 - wc-modal

    在现代 Web 开发中,组件化已经成为了一种非常流行的开发方式。在这种开发方式中,组件可以看作是 Web 应用程序的构建块,通过封装可重用的代码和样式来实现高效的开发和维护。

    1 年前
  • 解决 Tailwind CSS 在桌面端 Chrome 中字体异常的问题

    背景 Tailwind CSS 是一款流行的 CSS 框架,它的设计思想是通过给 CSS 类名赋予语义化的名称,来快速搭建页面。Tailwind CSS 的特点是提供了大量的 CSS 类名,开发者可以...

    1 年前
  • Mocha 测试中如何配置测试环境

    简介 Mocha 是一个 JavaScript 测试框架,它可以在浏览器和 Node.js 环境下运行。在前端开发中,我们经常需要编写测试代码来保证代码质量和稳定性。

    1 年前
  • 解决 Webpack 构建过程中压缩图片会导致 404 错误的问题

    在前端开发中,使用 Webpack 进行构建已经成为了常态。在 Webpack 的构建过程中,我们通常会使用一些插件来优化构建效率和资源体积。其中,压缩图片是一个常见的优化手段。

    1 年前
  • ESLint 与 Prettier 的对比及结合使用方法指南

    随着前端技术的不断发展,代码规范的重要性越来越被大家所认识。而在前端开发中,ESLint 和 Prettier 是两个常用的代码规范工具。本文将介绍 ESLint 和 Prettier 的对比,以及如...

    1 年前
  • Babel 编译报错:Unexpected token import 的解决方法

    在前端开发中,我们经常会用到 ES6 的模块化语法 import/export,然而在使用 Babel 编译时,有时候会出现 Unexpected token import 的错误,这是因为 Babe...

    1 年前
  • Chai 和 Angular 结合使用进行单元测试及常见问题解决方法

    单元测试是前端开发中不可或缺的一部分,它可以帮助我们及时发现代码中的问题,提高代码质量,减少 bug 的出现。在进行单元测试时,Chai 是一个非常好用的断言库,它可以让我们方便地编写和执行测试用例。

    1 年前
  • Docker 容器优雅关闭的方法详解

    Docker 是一个开源的容器化平台,可以帮助开发者快速构建、发布和运行应用程序。在使用 Docker 时,我们经常需要启动和停止容器。而在停止容器时,如果直接使用 docker stop 命令,会导...

    1 年前
  • ES6 中的 Async 和 Await 实现异步操作的全面指南

    随着前端技术的不断发展,异步操作在前端开发中越来越常见。而 ES6 中的 Async 和 Await 则为异步操作的实现提供了更加优雅和简单的方式。本文将全面介绍 ES6 中的 Async 和 Awa...

    1 年前
  • Socket.io 实现实时音视频通话功能教程

    在现代网络应用中,实时音视频通话已成为越来越重要的功能,如何实现实时音视频通话呢?本文将介绍使用 Socket.io 实现实时音视频通话的方法。 什么是 Socket.io? Socket.io 是一...

    1 年前
  • Serverless 架构的 SLA 保障与监控机制

    随着云计算技术的发展,Serverless 架构作为一种新型的应用架构方式,已经成为了越来越多企业的首选。Serverless 架构的最大优势在于能够大幅降低运维成本和开发成本,同时也能够提高应用的弹...

    1 年前
  • 解决 Node.js 中 ES11 对全局对象的更改

    随着 ECMAScript(以下简称 ES)版本的不断更新,我们可以看到 JavaScript 语言不断地在扩展和改进。ES11 中引入了一些新的全局对象和函数,如 globalThis、BigInt...

    1 年前
  • Next.js 中如何做页面 SEO 优化?

    SEO(Search Engine Optimization)是指通过优化网站结构和内容,提高网站在搜索引擎上的排名,从而获得更多的流量和曝光度。在前端开发中,如何做好页面 SEO 优化是非常重要的一...

    1 年前
  • Kubernetes 中自动伸缩(Autoscaling)的最佳实践

    在 Kubernetes 中,自动伸缩(Autoscaling)是一种非常有用的功能,可以根据负载自动调整 Pod 的数量,以确保应用程序的可用性和性能。本文将介绍 Kubernetes 中自动伸缩的...

    1 年前
  • 如何优化 PWA 的启动速度

    什么是 PWA PWA(Progressive Web App)是一种新型的 Web 应用程序,它具有类似原生应用的功能和体验,但是不需要安装即可使用,可以在任何支持浏览器的设备上运行。

    1 年前
  • 使用 Jest 测试 React Native 应用的详细教程

    在前端开发中,测试是一个非常重要的环节。而在 React Native 开发中,使用 Jest 进行测试是一种非常常见的方式。本文将为你介绍如何使用 Jest 测试 React Native 应用,并...

    1 年前
  • Headless CMS 的缓存机制及其实现方式探析

    前言 随着前端技术的发展,越来越多的网站开始采用 Headless CMS 的架构模式。Headless CMS 是一种将内容管理系统与前端界面分离的架构模式,它提供了一种灵活、可扩展、可定制的方式来...

    1 年前

相关推荐

    暂无文章