我正在使用 Vuex
管理执行登录和登录状态。这是一个标准程序:
Vuex
操作以使用凭据向 Node/Express 端点 axios
发出 /api/login
API 调用state.user
突变发回存储在 setUser
对象中的用户数据。 state.user.isLoggedIn
的标志也设置为 true
。以上都按预期工作。但是,如果用户刷新浏览器,则 Vuex
状态将被清空,站点标题不再显示用户信息。为了克服这个问题,我将 state.user
作为持久数据存储到浏览器中的 localStorage
中,并在页面刷新时使用 Vuex
中的数据重新填充 localStorage
存储。如果用户退出,localStorage
将被清除。
有很多路由需要检查用户是否登录。我不能依赖localStorage
,因为它可以被用户操纵。如果用户删除了包含 JWT 的 cookie,那么 localStorage
不会被清空,站点标题仍会显示他们的登录信息。因此,我需要在几乎每个页面上进行 API 调用,以检查用户是否已登录,如果未登录,则删除 localStorage
。
我的问题是:
app
时还是在 vue-router
内使用 beforeEach
导航守卫?beforeEach
中使用 vue-router
,每次用户更改路线时都会通过对 /api/login
进行 API 调用而导致网站崩溃吗?在每条路线上都这样做是正常的做法吗?答案 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% 的繁重工作。