如何使用Vuex保持用户登录?

时间:2021-06-15 12:13:29

标签: vue.js vuex vue-router vuejs3

我正在使用 Vuex 管理执行登录和登录状态。这是一个标准程序:

  1. 用户在表单上提交他们的登录详细信息
  2. 该表单调度 Vuex 操作以使用凭据向 Node/Express 端点 axios 发出 /api/login API 调用
  3. 如果成功,来自 API 的响应将通过 state.user 突变发回存储在 setUser 对象中的用户数据。 state.user.isLoggedIn 的标志也设置为 true
  4. 一个 JWT 访问令牌被发送到用户的浏览器并存储在一个安全的 cookie 中,以便反复使用,直到它过期。如果过期,则使用刷新令牌生成新的 JWT 访问令牌。
  5. 站点的标题显示用户的登录信息,例如姓名

以上都按预期工作。但是,如果用户刷新浏览器,则 Vuex 状态将被清空,站点标题不再显示用户信息。为了克服这个问题,我将 state.user 作为持久数据存储到浏览器中的 localStorage 中,并在页面刷新时使用 Vuex 中的数据重新填充 localStorage 存储。如果用户退出,localStorage 将被清除。

有很多路由需要检查用户是否登录。我不能依赖localStorage,因为它可以被用户操纵。如果用户删除了包含 JWT 的 cookie,那么 localStorage 不会被清空,站点标题仍会显示他们的登录信息。因此,我需要在几乎每个页面上进行 API 调用,以检查用户是否已登录,如果未登录,则删除 localStorage

我的问题是:

  1. 每次访问页面/视图时,我在哪里执行登录检查?是在安装 Vue app 时还是在 vue-router 内使用 beforeEach 导航守卫?
  2. 如果我在 beforeEach 中使用 vue-router,每次用户更改路线时都会通过对 /api/login 进行 API 调用而导致网站崩溃吗?在每条路线上都这样做是正常的做法吗?
  3. 是否有其他替代模式可以跟踪用户是否登录?

1 个答案:

答案 0 :(得分:2)

像这样的应用程序决策往往是主观的,因为每个应用程序都是不同的,具有不同的要求和不同的架构。听起来这是一个单页应用程序,所以我将从那里开始。

首先,您的 JWT 已经设置好并且可以正常工作这一事实非常棒 - 这可能是一项艰巨的工作,因此为您取得如此大的成就感到自豪。

如果您的应用程序具有某些无需先登录即可访问的页面(例如登录页面或拒绝访问页面等),那么您也必须在设计中考虑这一点。在这种情况下,beforeEach 路由保护是阻止路由加载或在未登录用户尝试请求可能只会给他们错误的内容之前捕获这些用户的完美解决方案。

您可能不必每次用户导航到新页面时都对服务器进行 API 调用。那可能会有点慢。因为您的应用程序使用 JWT,并带有刷新令牌,所以您应该能够依赖它们,这样如果用户登录,他们将继续登录,直到他们关闭浏览器并离开。

这就是为什么你不应该使用 localStorage。 When a tab closes or even after a reboot, the user will still appear to be logged in. Instead of using localStorage, use sessionStorage - Helpful MDN link.< /p>

现在,检索 user 对象的登录事件应该在每个浏览器标签页只发生一次,但在访问期间保持活动状态。

我想知道为什么您不只是在刷新浏览器时从服务器请求一个新的 user 对象。强制重新检查服务器以加载完整页面并不奇怪。这样做意味着你不必使用 Vuex 之外的任何东西来存储用户的状态

接下来,有没有办法在导航事件期间检查其 JWT 的有效性?根据您处理 JWT 的方式,您可能有权访问它,并可能对其进行解码(例如通过 oidc-client-js 库),并通过这种方式自行确定令牌是否已过期。但是,如果令牌已过期,您的令牌刷新系统可能只是刷新它而不会告诉您。

您还可以观察您的 HTTP 请求并注意 401 或 403 响应(但是您的后端处理已注销的用户),如果您看到其中之一,则将用户引导回登录屏幕。您可以使用 Axios 的全局拦截器来捕获它们,或者如果您将调用 Axios 的位置集中起来,您可以自己做。

总的来说,您已经在路上了,并且显然对此有很好的把握。到目前为止取得了巨大的进步,大概已经完成了 90% 的繁重工作。

相关问题