VUE 3,VUE Router 4 Navigation Guards和Pinia商店
我正在尝试使用JWT身份验证的应用程序创建一个VUE 3,并使用Pinia Store中的“ Isauth”变量匹配路由器的问题,以检查访问。最终,整个负载的Vue路由器和应用程序比商店更快,这就是为什么我总是从商店中获得“未经授权”的值,但实际上用户已登录并且他的数据在商店中。 我将尝试描述为注册和登录用户所做的所有步骤。
- 对Nodejs后端进行了注册,并创建了JWT令牌。
- 在登录屏幕上,用户输入电子邮件和密码,如果信息有效,他将被登录,JWT将保存到localStorage并通过JWTDecode进行解码,解码的令牌数据将保存在用户变量中,并将其保存到商店中,并将其设置为TRUE变量。 。
- Pinia商店有2个状态字段:用户(最初为null)和Isauth(最初为false)。
- 在主应用程序组件中,我使用的是Async onmounted Hook检查令牌,并通过调用API方法来保持用户登录,该方法比较JWT。
- 在VUE路由器中,我有几条必须保护未经授权的用户的路线,这就是为什么我试图通过从商店中检查用户信息来为其创建导航警卫的原因。问题是,路由器是在设置用户信息之后创建的,并且始终获取用户和ISAUTH变量的初始状态。
代码:
store
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();
});
我觉得这个问题是异步检查的问题,但无法弄清楚如何重写它要在应用程序初始化之前加载存储。
我希望有人也遇到这个问题并可以提供帮助。
提前致谢!
I'm trying to create an Vue 3 with app with JWT authentication and meet an issue with guarding the router using "isAuth" variable from Pinia store to check the access. Eventually Vue router and app in whole loads faster than the Store, that's why I'm always getting "unauthorized" value from the store, but in fact user is logged in and his data is in store.
I'll try to describe all the steps that are made to register and login user.
- Registration is made to NodeJS backend and JWT token is created.
- On the login screen user enters email and password, if info is valid he will be logged in and JWT will be saved to localstorage and decoded through JWTdecode, decoded token data will be saved to the store in user variable, and isAuth variable set to true.
- Pinia store has 2 fields in state: user(initially null), and isAuth(initially false).
- In the main App component I'm using async onMounted hook to check the token and keep user logged in by calling the API method, which compares JWT.
- In the Vue router i have several routes that must be protected from the unauthorized users, that's why I'm trying to create navigation guards for them by checking the user information from the store. Problem is, router is created after the setting user info and is always getting the initial state of the user and isAuth variables.
Code:
Store
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 guard sample
router.beforeEach((to, from, next) => {
const store = useLoggedInUserStore();
if (!store.isAuth && to.name !== 'Login') next({ name: 'Login' });
else next();
});
I feel that problem is with this async checking, but can't figure out how to rewrite it to load store before the app initialization.
I hope that somebody meet this problem too and can help.
Thanks in advance!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
因此,我刚刚遇到了这个问题,并因此解决了该问题,请此解决方案
正如它所说,路由器在
app应用之前实例化。
> isauth 检查
user
是否不是null,例如:也不建议将JWT存储在本地存储中,就好像您接触了XSS攻击,可以偷走令牌。您至少应该将其存储在httponly cookie中(这意味着它无法从JavaScript访问),它可以使用Express来实现。
So I just met this problem and fixed it thanks to this solution
As it says, the router gets instantiated before
App.vue
is fully mounted so check the token inbeforeEach
instead, like:By the way instead of having an action
setAuth
you could just use your getterisAuth
checking ifuser
is not null, like:Also it's not recommended to store a JWT in the local storage as if you're site is exposed to XSS attacks the token can be stolen. You should at least store it in an HttpOnly cookie (meaning it's not accessible from JavaScript), it's super easy to do with Express.
首先,我想说,使用 App.vue 和生命周期钩子是一个糟糕的实现,尽量不要那样使用它。
创建 authGuard.ts:
将路由器防护添加到您的路由器配置中:
您可以在存储文件中定义自定义的 isAuthenticated 检查器。
希望有帮助!这是一个基本的实现,应该根据您的需要进行重构。
First of all, I want to say that using
App.vue
and the lifecycle hooks is a bad implementation, try not to use it like that.Create
authGuard.ts
:Add the router guard to your router configuration:
You can define your custom
isAuthenticated
checker in the store file.Hope it helps! It's a basic implementation and should be refactored according to your needs.