查看 3、查看路由器 4 Navigation Guards 和 Pinia 商店

Vue 3, Vue Router 4 Navigation Guards and Pinia store

我正在尝试使用具有 JWT 身份验证的应用程序创建 Vue 3,并遇到使用 Pinia 商店中的“isAuth”变量保护路由器以检查访问权限的问题。最终 Vue 路由器和应用程序的整体加载速度比商店快,这就是为什么我总是从商店获得“未经授权”的价值,但实际上用户已登录并且他的数据在商店中。 我将尝试描述注册和登录用户的所有步骤。

  1. 向 NodeJS 后端注册并创建 JWT 令牌。
  2. 在登录界面用户输入邮箱和密码,如果信息有效,他将被登录,JWT 将被保存到本地存储并通过 JWTdecode 解码,解码后的令牌数据将被保存到存储在用户变量中,并且isAuth 变量设置为 true。
  3. Pinia 商店有 2 个状态字段:user(最初为 null)和 isAuth(最初为 false)。
  4. 在主 App 组件中,我使用异步 onMounted 钩子来检查令牌并通过调用比较 JWT 的 API 方法保持用户登录。
  5. 在 Vue 路由器中,我有几个必须防止未经授权用户访问的路由,这就是为什么我试图通过检查商店中的用户信息来为它们创建导航守卫。问题是,路由器是在设置用户信息之后创建的,并且总是获取用户的初始状态和 isAuth 变量。

代码:

店铺

import { defineStore } from 'pinia';

export const useLoggedInUserStore = defineStore({
  id: 'loggedInUser',
  state: () => ({
  isAuth: false,
  user: null
   }),

  getters: {
  getisAuth(state) {
  return state.isAuth;
    },
  getUser(state) {
  return state.user;
   }
  },
 actions: {
  setUser(user) {
  this.user = user;
  },
  setAuth(boolean) {
  this.isAuth = boolean;
   }
}
});

App.vue onMounted

 onMounted(async () => {
    await checkUser()
      .then((data) => {
         isLoading.value = true;
          if (data) {
          setUser(data);
          setAuth(true);
         } else {
         router.push({ name: 'Login' });
          }
       })
       .finally((isLoading.value = false));
       });

路由器防护样本

router.beforeEach((to, from, next) => {
   const store = useLoggedInUserStore();
   if (!store.isAuth && to.name !== 'Login') next({ name: 'Login' });
   else next();
});

我觉得这个异步检查有问题,但无法弄清楚如何重写它以在应用程序初始化之前加载存储。

我希望有人也遇到这个问题并能提供帮助。

提前致谢!

所以我刚刚遇到这个问题并解决了它感谢

正如它所说,路由器在 App.vue 完全安装之前被实例化,因此请检查 beforeEach 中的令牌,例如:

router.beforeEach(async (to, from, next): Promise<void> => {
  const user = useUser();
  await user.get();

  console.log(user) // user is defined

  if (to.meta.requiresAuth && !user.isLoggedIn) next({ name: "home" }); // this will work

顺便说一下,您可以使用 getter isAuth 检查 user 是否不为空,而不是执行操作 setAuth,例如:

isAuth: (state) => state.user !== null

另外,不建议将 JWT 存储在本地存储中,因为如果您的站点暴露于 XSS 攻击,令牌可能会被盗。您至少应该将它存储在一个 HttpOnly cookie 中(这意味着它不能从 JavaScript 访问),使用 Express 非常容易做到。