React.js SPA 应用实现登录超时自动跳转登录页面的方法

在基于 React.js 的单页应用(Single Page Application, SPA)中,我们经常需要实现用户登录认证功能,其中一个重要的需求就是当用户在一段时间内没有操作时,系统会自动跳转到登录页面以保护用户的信息安全。本文将介绍如何使用 React.js 来实现一种通用的登录超时自动跳转登录页面的方法。

1. 实现方案

在 SPA 中,路由(Route)是非常重要的一个概念,因为页面的切换通常是通过改变 URL 栏中的路径实现的。基于这一点,我们可以在路由组件上增加一个监听器,当用户没有操作时,记录当前时间;如果在某一段时间内没有操作,则跳转到登录页面。

具体实现步骤如下:

  1. 在 App 组件中添加一个 state,用于存储用户最后一次的操作时间:
------ ----- ---- --------

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

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

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

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

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

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

在 componentDidMount 和 componentWillUnmount 函数中,我们分别对 window 对象绑定和解除 mousemove 和 keydown 事件的监听器。当用户有这两种事件时,handleUserActivity 函数会更新 lastActiveTime 状态值。

  1. 在每个需要验证登录状态的路由组件中,判断当前时间和 lastActiveTime 的差值是否超过一定的时间(例如 30 分钟),如果超时,则自动跳转到登录页面:
------ ----- ---- --------
------ - -------- - ---- -------------------

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

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

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

在 ProtectedRoute 组件中,我们判断用户是否处于登录状态,然后通过 localStorage 获取用户最后一次的操作时间 lastActiveTime。如果时间超过 timeout,就通过 Redirect 组件将用户自动跳转到登录页面。

2. 存在问题

然而,我们发现在单页应用中实现自动跳转存在以下问题:

  1. 在路由组件中增加重定向等逻辑,导致代码中的业务逻辑混杂在组件内部,影响代码的可维护性和可读性。

  2. 不同路由组件中的验证逻辑可能会重复,造成代码冗余和难以维护。

  3. 如果浏览器中有多个页面处于登录状态,用户操作其中任何一个页面都会更新其他页面的 lastActiveTime,这显然不符合用户体验的预期。

3. 解决方案

为了解决以上问题,我们可以考虑使用一个名为 AuthService 的服务类来管理用户的登录状态和验证逻辑。AuthService 封装了存储功能和验证功能,路由组件只需要从 AuthService 中获取当前用户的登录状态即可。

具体实现如下:

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

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

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

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

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

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

在 AuthService 构造函数中,我们初始化了用户的登录状态和最后一次操作时间。在 window 对象上监听了 storage 事件,并且在事件回调中更新了 AuthService 的状态值。这样,在一个页面中更新了用户的登录状态或最后一次操作时间后,其他页面也会及时得到更新。

AuthService 中还有两个方法:

  1. isAuthenticated:根据 AuthService 的状态值,判断用户是否处于登录状态且操作时间没有超时。

  2. redirectUnlessAuthenticated:如果用户没有处于登录状态或操作时间超时了,那么就通过 window.history 和 props.history 将用户自动跳转到登录页面。

现在,只需要在路由组件中调用 AuthService 中的 isAuthenticated 方法,通过这种方式来实现登录超时自动跳转到登录页面的功能:

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

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

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

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

在这个 ProtectedRoute 组件中,我们只需要调用 AuthService 的 isAuthenticated 和 redirectUnlessAuthenticated 方法,不需要再进行任何逻辑配置。AuthRoute 中的 isAuthenticated 和 redirectUnlessAuthenticated 方法将会自动根据 AuthService 中的状态值来判断用户是否应该跳转到登录页面。

AuthRoute 的配置也非常简单:

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

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

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

相对于之前的实现方式,使用 AuthService 的方式将路由组件和验证逻辑分离开来,大大提高了代码的可维护性和可读性。此外,AuthService 还可提供其他的验证逻辑、登录状态存储实现等功能,是一种非常通用的用户登录认证方案。

4. 总结

本文介绍了使用 React.js 实现 SPA 应用中的登录超时自动跳转登录页面的方法。通过这种方式,可以轻松实现登录认证的功能,并且将路由组件和验证逻辑分离开来,提高了代码的可维护性和可读性。我们还介绍了使用 AuthService 这个服务类管理用户登录状态和验证逻辑的方式,提供了一种通用的解决方案。

完整代码示例:

App.js:

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

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

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

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

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

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

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

AuthRoute.js:

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

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

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

AuthService.js:

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

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

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

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

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

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

LoginForm.js:

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

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

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

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

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

Dashboard.js:

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

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

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

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

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

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

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/648bef6848841e9894a38f95


猜你喜欢

  • 使用 Express.js 进行 Web 应用的跨域访问

    跨域访问是指在 web 应用中,浏览器发起的跨域请求被服务器拒绝。要解决这个问题,我们需要在服务器端进行相应的配置。在此,我们将介绍如何使用 Express.js 框架进行 web 应用的跨域访问。

    1 年前
  • 使用 Deno 构建 Web 服务,需要注意什么

    前言 Deno 是一个新兴的 JavaScript/TypeScript 运行时,由原始 Node.js 作者开发。它具有跨平台、安全性高和开发效率高等优点,已经在前端开发领域引起了广泛的关注。

    1 年前
  • Enzyme 中如何处理子 React 组件

    在 React 开发中,我们经常使用 Enzyme 这个库来进行组件测试。在测试过程中,涉及到了对于子组件的处理,那么本文将会详细介绍 Enzyme 中如何处理子 React 组件。

    1 年前
  • ESLint ignore 规则怎么写?

    在前端开发过程中,我们常常使用 ESLint 来帮助我们检测代码质量和规范性。但是有些时候,我们并不想让 ESLint 检测某些文件或者特定的代码段,这时我们就需要使用 ESLint 的 ignore...

    1 年前
  • 如何使用 ES6 中的 Proxy 处理对象拦截和代理

    在现代前端开发中,对象是一个非常重要的概念,然而在实际开发中,我们很难获得对对象完全的控制,某些对象的属性可能不能被修改、某些属性的访问需要做一些额外的操作等等。这时候,ES6 中的 Proxy 就能...

    1 年前
  • Serverless 框架下的完美 RESTful API 开发指南

    Serverless 框架下的完美 RESTful API 开发指南 随着云计算和微服务的不断发展,Serverless 架构已经逐渐成为了一种趋势和热门话题。相比于传统的 Web 应用开发方式,Se...

    1 年前
  • 基于 TailwindCSS 实现多屏幕适配

    在现代互联网的时代,响应式设计已经成为了前端开发不可缺少的一部分。多数情况下,现代 Web 设计基于流式布局的原理实现,而且需要计算元素在不同分辨率下的宽度和高度。

    1 年前
  • PM2 如何实现 Node.js 应用的自动化负载均衡

    随着 Node.js 的普及,越来越多的开发者开始使用 Node.js 来构建高性能的 Web 应用。然而,随着应用的不断扩展,单一 Node.js 服务可能无法满足需求,此时需要使用负载均衡来实现服...

    1 年前
  • 如何使用 PWA 技术实现离线支付

    介绍 PWA(渐进式网络应用程序)是一种新型的 Web 应用程序,它可以像原生应用程序一样工作,具有离线能力和更好的性能。离线支付是 PWA 中重要功能之一,可以在没有互联网连接的情况下进行支付交易。

    1 年前
  • 使用 normalize.css 和 reset.css

    在开发前端网页时,我们会发现在不同浏览器上,同样的 CSS 样式可能会因为浏览器的不同实现,而导致页面呈现的不一致。为了解决这个问题,有人提出了 Reset CSS 的概念。

    1 年前
  • Cypress 测试时如何断言一个元素的样式是否符合预期

    前言 Cypress 是一个现代化的前端端到端(End-to-End)测试工具,它可以轻松地测试 Web 应用程序的各种方面,包括用户交互、网络请求、错误处理、DOM 中的状态以及样式等。

    1 年前
  • React Native 中的 UI 控件及其功能实现

    React Native 是一款跨平台开发框架,它使用 JavaScript 和 React 来构建 iOS、Android 和 Web 应用程序。它拥有许多强大的 UI 控件,这些控件可以帮助开发人...

    1 年前
  • Socket.io 如何实现 IP 屏蔽和封禁

    Socket.io 是一个非常流行的前端实时通信框架,通过它我们可以很方便的实现实时通信功能,但是在实际使用中,我们经常会遇到一些问题,比如遭到恶意攻击,需要屏蔽或封禁某些 IP 地址。

    1 年前
  • 如何使用 Node.js 和 MongoDB 构建一个简单的博客?

    Node.js 是一个流行的后端 JavaScript 开源运行环境,它可以让你使用 JavaScript 来编写服务器端应用程序。而 MongoDB 是一个流行的 NoSQL 数据库,它可以存储半结...

    1 年前
  • RESTful API 中的 HTTP 请求头

    在前端开发中,我们经常需要与后端进行数据交互。而使用 RESTful API 已经成为了一种流行的方式。在实现 RESTful API 调用时,我们需要了解相关的 HTTP 请求头信息。

    1 年前
  • React.js 中如何应用响应式设计

    响应式设计已经成为现代 web 开发中一个非常重要的概念。在不同的设备和屏幕尺寸下,网页的布局和内容应该能够动态地适应以提供最佳的用户体验。React.js 是一个流行的前端框架,它提供了一些工具和技...

    1 年前
  • 浅谈 ES10 对象新特性

    随着 JavaScript 语言的发展,ES10 在对象方面引入了一些新的特性,这些特性不仅让开发者编写更加简洁易读的代码,还可以提升应用程序的性能。本文将深入探讨 ES10 中对象的新特性,并附带示...

    1 年前
  • Webpack 打包后文件过大,如何优化

    Webpack 打包后文件过大,如何优化 Webpack 是现代 Web 开发中不可或缺的工具,它可以帮助我们自动化构建、打包和优化 Web 应用程序,简化开发流程,提高开发效率。

    1 年前
  • 利用 Docker 构建基于 Django 的 Web 应用服务

    Docker 是一个流行的容器化技术,它可以让开发者轻松地将应用程序打包进容器中,并且能够提供开发、运行和部署的标准化环境。本文将介绍如何使用 Docker 构建一个基于 Django 的 Web 应...

    1 年前
  • 如何使用 ES6 中的解构和默认参数功能简化你的函数

    在前端开发中,我们经常需要编写函数来完成一些操作。但是,有时候我们写的代码会变得冗长复杂,影响代码的可读性和可维护性。而 ES6 中的解构和默认参数功能可以让我们更加简洁高效地编写函数。

    1 年前

相关推荐

    暂无文章