Vue中如何维持登录用户状态并实现页面权限控制?
嘿,从PHP服务端直接靠会话判断跳转,转到Vue单页应用做登录授权,确实得换个思路——毕竟Vue是前端路由主导的,核心要靠路由守卫配合后端校验来实现。我结合你之前的PHP逻辑,一步步给你拆解怎么搞:
1. 先搞定Vue Router基础配置
首先你得用Vue Router(Vue官方路由工具,没装的话先执行npm install vue-router),先定义路由表,把需要登录的页面和登录页区分开:
// src/router/index.js import Vue from 'vue' import VueRouter from 'vue-router' import Home from '../views/Home.vue' // 你的需登录页面 import Login from '../views/Login.vue' // 登录页 Vue.use(VueRouter) const routes = [ { path: '/', name: 'Home', component: Home, meta: { requiresAuth: true } // 标记该路由需要登录权限 }, { path: '/login', name: 'Login', component: Login }, // 其他路由同理,需要登录的就加meta.requiresAuth字段 ] const router = new VueRouter({ mode: 'history', // 可选,去掉URL里的#号,需要后端配置支持 routes }) export default router
2. 全局路由守卫:替代你原来的PHP会话判断
这就对应你之前那段if ($_SESSION['user_id'] > 0)的逻辑——每次路由跳转前,前端先检查登录状态,同时必须和后端校验(避免前端本地存储被篡改):
先写后端的校验接口(比如check-login.php):
<?php session_start(); header('Content-Type: application/json'); $response = ['loggedIn' => false]; if (isset($_SESSION['user_id']) && $_SESSION['user_id'] > 0) { $response['loggedIn'] = true; // 可以顺便返回用户信息,比如$response['user'] = ['id' => $_SESSION['user_id'], 'name' => $_SESSION['username']]; } echo json_encode($response); ?>
然后在Vue的路由守卫里调用这个接口:
// 继续在src/router/index.js里添加 router.beforeEach(async (to, from, next) => { // 判断当前路由是否需要登录权限 const requiresAuth = to.matched.some(record => record.meta.requiresAuth) if (requiresAuth) { // 需要登录,调用后端接口校验 try { const res = await fetch('/check-login.php') const data = await res.json() if (data.loggedIn) { // 已登录,放行 next() } else { // 未登录,跳登录页,同时记录当前目标路由,登录后可跳转回来 next({ name: 'Login', query: { redirect: to.fullPath } }) } } catch (err) { // 请求失败,默认跳登录页 next({ name: 'Login' }) } } else { // 不需要登录的路由直接放行 // 额外处理:如果用户已登录,访问登录页自动跳首页 if (to.name === 'Login') { const res = await fetch('/check-login.php') const data = await res.json() if (data.loggedIn) { next({ name: 'Home' }) } else { next() } } else { next() } } })
3. 登录成功后的重定向处理
当用户在登录页提交表单,调用你原来的PHP登录接口(成功后设置SESSION),登录成功后要跳转到用户之前想访问的页面(如果有的话),否则跳首页:
// src/views/Login.vue里的登录方法 async login() { try { const res = await fetch('/login.php', { method: 'POST', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, body: `username=${this.username}&password=${this.password}` }) const data = await res.json() if (data.success) { // 获取路由里的redirect参数,没有的话默认跳首页 const redirect = this.$route.query.redirect || '/' // 跳转到目标页面 this.$router.push(redirect) } else { alert('登录失败:' + data.message) } } catch (err) { alert('登录请求失败') } }
4. 补充:前端状态管理(可选但推荐)
如果你的应用比较复杂,用Vuex管理登录状态会更方便,不用每次都调用后端接口(可以缓存状态,定期校验):
// src/store/index.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) export default new Vuex.Store({ state: { isLoggedIn: false, userInfo: null }, mutations: { SET_LOGIN_STATE(state, payload) { state.isLoggedIn = payload.loggedIn state.userInfo = payload.userInfo } }, actions: { async checkLogin({ commit }) { const res = await fetch('/check-login.php') const data = await res.json() commit('SET_LOGIN_STATE', { loggedIn: data.loggedIn, userInfo: data.user || null }) return data.loggedIn } } })
之后路由守卫里就可以调用Vuex的action:
// 路由守卫里修改 const isLoggedIn = await store.dispatch('checkLogin') if (isLoggedIn) { next() } else { next({ name: 'Login', query: { redirect: to.fullPath } }) }
最后注意点
- 如果用了
history模式,需要在后端(Nginx/Apache)配置重定向,把所有请求指向index.html,否则刷新页面会404 - 前端本地存储(localStorage)不能完全信任,必须和后端校验登录状态,避免伪造登录
- 退出登录时,要调用后端接口销毁SESSION,同时清空前端状态
内容的提问来源于stack exchange,提问作者Kalreg
相关产品推荐
相关产品推荐

