如何在 React 应用程序中使用 Token 对用户进行身份验证

如何在 React 应用程序中使用 Token 对用户进行身份验证

身份验证是每个涉及公共和私有页面的优秀应用程序的重要组成部分,因此了解如何实现它以及它的执行流程是很重要的。

在本文中,我将解释什么是基于令牌的身份验证,身份验证流程是如何工作的,然后我将向您展示如何在 React.js 应用程序中设置基于令牌的身份验证。

这篇文章将要求你对 React.js 中使用的重要术语有一些基本的了解,所以为了顺利地跟随你应该熟悉或者至少对什么是自定义钩子有基本的了解,如何在 React 中使用条件操作.js 以及如何使用内置的 React.js 钩子,例如 useState 钩子。

如果你想看完整的项目看看感觉如何,你可以克隆存储库 这里 ,然后使用 npm start 在您的机器上运行它。请注意,您的服务器必须正在运行,因此您必须打开一个新终端并运行 node server.js 来运行您的服务器并对其进行测试

本文将分为以下几个部分:

  1. 什么是基于令牌的身份验证
  2. 如何设置 React.js 项目和页面
  3. 设置应用程序的服务器以生成令牌
  4. 如何存储用户的令牌
  5. 结论

什么是基于令牌的身份验证

基于令牌的身份验证是使用身份验证令牌在应用程序和网站之间安全地传输用户身份。此过程使组织能够提高其身份验证过程的效率。

它只是一个生成加密和安全令牌的过程,并允许用户在成功提交这些令牌后提出验证请求。将其存储以进行进一步的身份验证。

在指定的时间段后,一个好的身份验证令牌将过期,让身份验证令牌处于活动状态的时间过长会使应用程序容易受到攻击,因为劫持者可以利用此漏洞劫持用户会话。

从上面的简单定义你应该明白,基于令牌的身份验证有 5 个执行步骤,它们是:

  1. 用户通过提供必要的登录凭据来发出请求
  2. 通过授予用户访问令牌来处理和验证此请求
  3. 然后将访问令牌提交给浏览器以授予用户访问会话的权限。
  4. 将这些身份验证令牌存储在应用程序中以进行进一步身份验证也很重要,并且有很多方法可以做到这一点。我们将在本文后面的令牌存储部分对此进行介绍。
  5. 最后,为了保护您的应用程序的用户免受网络攻击,有必要为生成的令牌设置超时到期。

有五种主要类型的令牌可用于识别和授予用户对设备或应用程序的访问权限。

这些令牌可用于物理设备和软件应用程序,它们包括:

  1. 软件令牌
  2. 断开连接的令牌
  3. JSON 网络令牌 (JWT)
  4. 连接令牌
  5. 非接触式令牌。

上面提到的每个令牌都有其特定的用例。

有了这个,我相信你一定已经很好地理解了什么是基于令牌的身份验证,在接下来的部分中,你将学习如何在 React.js 应用程序中设置基于令牌的身份验证并保护应用程序中的私有页面。

设置 React.js 项目和页面

在开始本节之前,我将设置我的 React.js 项目,并在我的项目中创建两个组件(主页和仪表板),然后将这些组件显示在不同的页面上,也称为路由。

在您希望 React.js 项目所在的项目目录中,运行以下命令:

这将设置一个 React.js 项目文件夹,其中包含运行它所需的所有必要文件和文件夹。

在您想要使用的任何代码编辑器中打开您的 React.js 项目。我正在使用 VScode。

在 App.js 文件中,在 src 文件夹中编辑并删除标题标签,因此您的 App.js 文件应如下所示:

您将在应用程序中安装一些包。首先,我使用 tailwindcss 来设计我的应用程序,所以如果你想使用它,你可以通过以下过程快速安装它并为你的应用程序设置它:

导航到刚刚创建的 React.js 项目后,在终端中运行以下命令,以在应用程序的依赖项中安装 tailwindcss、postcss 和 autoprefixer:

然后运行下面的命令生成tailwind.config.js文件和postcss.config.js文件:

通过将以下代码添加到 module.exports 对象的内容数组来配置 tailwind.config.js 文件:

上面的代码将为您的模板文件配置路径。从上面的代码中可以看出,您要求 tailwindcss 在 src 文件夹中具有 .js、.jsx、.ts 和 .tsx 扩展名的所有文件中执行。

使用此指令,您的 tailwindcss 样式将添加到这些文件中,您可以在其中使用它。

最后,在您的 React.js 项目的 index.css 文件中使用以下代码为应用程序的每一层添加@tailwind 指令:

这就是在您的应用程序中设置tailwindcss。让我们继续添加其他依赖项。

您将在我们的应用程序中添加路由机制,因此您需要 react-router-dom,还需要 cors 用于在应用程序页面之间共享信息,还需要 express 为您的应用程序设置后端服务器应用程序。

运行以下命令安装 react-router-dom:

cors 和 express 将作为 dev-dependencies 安装,因此,运行以下命令来安装它们:

您拥有启动应用程序所需的一切,但在我们运行启动脚本之前,让我们为我们的应用程序添加一点样式。

通过修改 index.css 文件中的代码将应用程序的背景颜色变为黑色:

现在运行启动脚本以在 localhost:3000 上查看您的应用程序。现在您应该看到您的应用程序具有完全黑色的背景。

在 src 文件夹中创建另一个名为“Components”的文件夹。在 Components 文件夹中创建 Homepage.jsx 和 Dashboard.jsx 文件。

这些文件将分别存放我们的主页和仪表板组件。

将以下代码添加到 Homepage.jsx 文件中以创建一个 Homepage 组件,该组件将在浏览器中显示一个简单的“主页”消息

在 Dashboard.jsx 文件中添加以下代码以创建 Dashboard 组件:

最后,将这些组件导入到 App.js 文件中,并将它们放在不同的页面上。

从 react-router-dom 导入 BrowserRouter、Routes 和 Route。并使用它们在单独的页面上设置这些组件,代码如下:

如果您访问 localhost:3000,您应该会看到 Homepage 组件。

如果您访问 localhost:3000/Dashboard,您也应该会看到 Dashboard 组件。

但是,目前您的仪表板组件不是私有的,每个人都可以访问它,它必须是私有的。

对于访问仪表板页面的用户,他们需要在登录表单中提供用户名和密码,以请求获取身份验证令牌。因此,您也将使用此表单创建一个登录组件。

在应用程序的 src 文件夹中再次创建一个文件夹并将其命名为 Login。

好吧,不必总是创建一个新文件夹来包装组件,但作为一个好的约定,最好将组件分组到单独的文件夹中。因此,由于我们拥有具有相同功能的 Homepage 和 Dashboard 组件,因此我们将它们保存在同一个文件夹中。

在 Login 组件中创建一个 Login.jsx 文件,并在此文件中创建一个 Login 组件并使用以下代码设置登录表单的样式:

在仪表板组件中设置一个逻辑,当用户尝试在没有适当身份验证的情况下访问仪表板页面(生成令牌)时,将向您的用户显示此登录表单。

在 Dashboard.jsx 文件中,从 react 中导入 useState 钩子,这将用于存储生成的令牌以授予用户访

之后,如果用户没有令牌,则使用条件语句呈现登录表单。

因此,将您的仪表板组件修改为如下所示:

保存 Login.jsx 和 Dashboard.jsx 文件,在您的应用程序仍在运行的情况下打开浏览器,导航到 localhoast:3000/Dashboard,您将看到 Login 表单而不是 Dashboard 页面。

太好了,现在您有一个受登录表单保护的私人页面,但现在的问题是您的登录表单无法正常工作,这是因为您尚未为经过身份验证的用户生成令牌。

但是您已经成功完成了使用token进行身份验证的第一步,也就是给用户一个平台来发出请求,也就是Login表单。

在下一部分中,您将创建一个后端服务器,该服务器将创建一个生成的令牌并将其发送给经过身份验证的用户。

设置应用程序服务器以生成令牌

在上一节中,您在应用程序中创建了一个受登录页面保护的私有页面。

在本节中,您将在项目目录的根目录中创建一个 sever.js 文件。

在这个文件中,您将使用 express 和 cors 创建一个服务器应用程序,该应用程序将向您的前端应用程序发送一个令牌,并在用户使用登录表单发出请求时授予访问权限。

因此,在项目目录的根目录下创建一个 server.js 文件,即创建 server.js 文件后,您的项目文件夹结构应如下所示:

在此 server.js 文件中添加以下代码以创建服务器应用程序:

从上面的代码中,您导入 express 或 required express 并将其传递到第 1 行中名为 express 的变量中,然后在第 2 行中您需要 cors 并将其传递给 cors 变量。在第 4 行中,您创建了一个 app 变量并将 express 变量传递给它。在第 5 行中,您通过将 cors 作为参数传递给 app.use() 方法,要求服务器应用程序使用 cors 包。

然后从第 7 行到第 11 行,您向服务器应用程序发出请求,将令牌对象发送到应用程序的登录路由,最后在第 13 行,您要求应用程序侦听端口 8080 并注销“API is running on localhost:8080/login”,当你运行你的服务器应用程序时。

要查看这是否真的有效,请在 VScode 中打开另一个终端并运行 node server.js,您应该会直接在终端中看到“API is running on localhost:8080/login”。完美,你有一个正在运行的服务器。

您需要让您的登录组件发出请求以从您刚刚创建的后端服务器应用程序中获取此令牌。

为此,请在 Login 组件中解构您从 Dashboard 组件传递的 setToken 属性,方法是添加 PropType,然后拉出 setToken 属性。因此,将 Login.jsx 文件修改为如下所示:

创建一个函数,该函数将向您创建的服务器应用程序发出 POST 请求。

这将是一个异步函数,它将凭据作为参数,然后使用 POST 请求调用 fetch 方法。

因此,就在 Login 组件之前,在所有导入之后,添加以下代码以创建异步函数:

最后,您将创建两个状态,一个将保存用户名值,另一个将保存密码值,您还需要添加一个句柄提交函数,该函数将调用您刚刚创建的 LoginUser 函数并设置用户令牌,并且在登录表单中的每个字段上添加 onChange 事件,以便您的应用程序能够接收用户的输入值。

将您的登录表单修改为如下所示:

整个登录组件的代码应如下所示:

保存文件并在服务器应用程序仍在运行的情况下返回浏览器,输入一些登录凭据,您应该导航到仪表板组件。

我们将令牌存储在应用程序的本地状态变量中,但这给我们带来了一个问题。现在,我们的应用程序将在用户每次刷新页面或打开新选项卡时向他们显示登录表单。

根据应用程序的要求,这可能不是一个很好的解决方案。为了解决这个问题,我们可以将令牌存储在 localStorage 或 sessionStorage 中。这样,您的用户即使刷新页面或打开新选项卡也将保持登录状态。

尽管将令牌存储在本地和会话存储中具有各自不同的安全含义,但我仍将展示如何在其中存储令牌并在下一节中解释它们的安全风险。

如何存储用户的令牌

您创建了一个有效的登录表单,但现在您的应用程序不能长时间保持用户的会话。

因此,如果用户应该刷新页面或打开一个新选项卡,会话将结束,用户将不得不再次提供他们的凭据。

尽管您现在将用户令牌存储在本地状态变量中,但您也可以将令牌存储在会话存储中,以使用户能够在会话持续期间保持登录状态,或者您可以决定将其存储在本地存储中。

但是存储在本地存储中也有它自己的缺陷,因为它使用户永远登录,直到令牌从本地存储中被取走。

因此,让我向您展示如何在会话和本地存储中存储用户的令牌

会话存储

要使用会话存储,请在仪表板页面中删除令牌状态并创建 setToken 和 getToken 函数,然后将 getToken 函数分配给令牌变量。

因此,您的仪表板组件的代码应如下所示:

您将使用 setToken 函数将用户生成的令牌保存到会话中。为此,您将使用 setItem 方法。 setItem 方法接受两个参数,一个键和一个字符串值。

因此,如果要使用 setItem 方法设置用户令牌,则必须使用 JSON.stringify 方法将令牌从 JSON 对象转换为字符串。

调用 setItem 方法并将令牌保存在会话中,代码如下:

有了这个,您已经成功地将用户的令牌保存在应用程序的会话存储中。但是您仍然需要从会话存储中检索此令牌并将其存储在您的应用程序中,以便您的应用程序可以使用它来向用户呈现所需的页面。

您可以使用 getItem 方法从会话存储中获取令牌。 getItem 方法接受一个键值作为它的唯一参数,然后返回一个字符串值。

因此,在 getToken 函数中添加 getItem 方法并使用以下代码从会话存储中检索用户令牌:

但是现在您需要在成功检索令牌时提醒您的应用程序,这使得用户即使在提供凭据后也无法登录。

为此,请创建一个带有令牌状态和 setToken 函数的自定义钩子,该函数将在成功检索令牌时触发重新呈现您的应用程序。

创建一个新文件夹并将其命名为 App,在 App 文件夹中创建一个名为 useToken 的新文件。

要创建自定义钩子,您必须使用前缀 *use,这就是我们使用 useToken 的原因。

在useToken文件里面导入useState并创建一个token状态和setToken函数,同时将getToken函数复制粘贴到useToken文件中,改成箭头函数。

还要从 Dashboard 组件中复制 setToken 函数,并将名称更改为 saveToken,因为您已经有一个名为 setToken 的函数,它负责设置应用程序的令牌值。

因此,您的 useToken 代码应如下所示:

最后在 Dashboard 组件中,导入并使用 useToken 钩子。

您不再需要 useState 挂钩,因为您不再将令牌存储在本地状态变量中,您也不需要 setToken 和 getToken 函数,因为您已经在 useToken 挂钩中拥有它们。

所以清除它们并使用以下代码在 Dashboard 组件中添加 useToken 钩子:

保存文件并在服务器应用程序仍在运行的情况下再次打开浏览器,您应该会看到登录表单,这次它工作得很好。

如果您打开新选项卡或刷新页面,您仍将登录应用程序并保留在仪表板页面上。

将会话令牌存储在应用程序的本地内存之外的安全风险在于,如果对应用程序的攻击成功,它会将这些令牌暴露给恶意用户,而且您需要实现一种在闲置一段时间后自动结束用户会话的方法避免会话劫持。

下一个存储方法是使用本地存储。此方法遵循与会话存储相同的方法。

您只需将自定义挂钩中的每个会话存储实例更改为 localStorage。

如果您正在使用 localStorage,请知道用户将永远登录到应用程序,即使您结束应用程序,您仍然会登录,直到您直接从 localStorage 清除令牌。

因此,这些是存储用户生成的令牌的方法,也是在应用程序中实现基于令牌的身份验证所采取的步骤

结论

身份验证在保护 Web 应用程序用户免受攻击和劫持方面起着非常重要的作用。实施适当的身份验证对于保持私有页面不被公开非常重要。

在本文中,我介绍了如何在 React 应用程序中使用令牌在正确识别后授予用户访问权限。在本文中,我向您展示了如何设置私有页面并仅在进行适当的身份验证和令牌发行后才显示它们。

我还向您展示了在应用程序中存储用户令牌的不同方法,以及优缺点。说明使用每种存储方法的风险和重要性。

感谢您跟进并阅读到最后。如果您有任何问题,请在评论中提出。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明

本文链接:https://www.qanswer.top/38398/44352111

posted @ 2022-09-21 11:45  哈哈哈来了啊啊啊  阅读(774)  评论(0编辑  收藏  举报