Vue3 权限系统(Pinia + 登录接口 + 权限刷新 + 路由守卫 )

文章目录

  • 零、最终效果
  • 一、先安装依赖
  • 二、完整代码结构
  • [三、1. Pinia 用户权限仓库(最重要)](#三、1. Pinia 用户权限仓库(最重要))
  • [四、2. 登录接口模拟](#四、2. 登录接口模拟)
  • [五、3. 路由配置 + 全局权限守卫](#五、3. 路由配置 + 全局权限守卫)
  • [六、4. 挂载 Pinia 到 main.js](#六、4. 挂载 Pinia 到 main.js)
  • [七、5. 登录页面示例(可直接用)](#七、5. 登录页面示例(可直接用))
  • [八、6. 403 无权限页面](#八、6. 403 无权限页面)
  • [九、7. 登出按钮(任意页面使用)](#九、7. 登出按钮(任意页面使用))
  • [十、你可以直接用的 3 种权限配置](#十、你可以直接用的 3 种权限配置)
  • 十一、这套系统的优势
  • [十二、 总结](#十二、 总结)

整合 Pinia + 登录接口 + 权限刷新 + 路由守卫 全套可直接上线的代码,复制即用,适配你要的 个别页面权限控制

零、最终效果

  • 登录后保存用户信息/权限到 Pinia + 持久化(刷新页面不丢失)
  • 路由守卫自动校验:未登录 → 跳登录、权限不足 → 跳403
  • 支持登录权限角色权限细粒度权限码三种控制
  • 登出自动清空状态、跳转登录
  • 刷新页面自动恢复权限

一、先安装依赖

bash 复制代码
# Pinia
npm install pinia

# Pinia 持久化(刷新不丢失权限)
npm install pinia-plugin-persistedstate

二、完整代码结构

复制代码
src/
├── stores/
│   └── user.js       # 用户权限仓库(核心)
├── router/
│   └── index.js       # 路由 + 守卫
├── api/
│   └── user.js        # 登录接口模拟
└── main.js            # 挂载 Pinia

三、1. Pinia 用户权限仓库(最重要)

src/stores/user.js

javascript 复制代码
import { defineStore } from 'pinia'
import { loginApi, logoutApi } from '@/api/user'

export const useUserStore = defineStore('user', {
  state: () => ({
    token: '',         // 登录令牌
    userInfo: {},      // 用户信息
    roles: [],         // 角色数组 ['admin', 'user']
    permissions: []    // 权限码数组 ['user:list', 'order:edit']
  }),

  // 持久化(刷新页面权限不丢失)
  persist: true,

  actions: {
    // 登录 + 获取权限
    async login(loginForm) {
      try {
        // 调用后端登录接口
        const res = await loginApi(loginForm)
        
        // 保存登录信息
        this.token = res.token
        this.userInfo = res.userInfo
        this.roles = res.roles
        this.permissions = res.permissions

        return Promise.resolve(res)
      } catch (err) {
        return Promise.reject(err)
      }
    },

    // 登出
    async logout() {
      await logoutApi()
      this.clearUserInfo()
    },

    // 清空信息
    clearUserInfo() {
      this.token = ''
      this.userInfo = {}
      this.roles = []
      this.permissions = []
    }
  }
})

四、2. 登录接口模拟

src/api/user.js

javascript 复制代码
// 模拟后端登录接口(真实项目替换成你的 axios 请求)
export function loginApi(loginForm) {
  return new Promise((resolve) => {
    setTimeout(() => {
      // 根据账号模拟不同权限
      if (loginForm.username === 'admin') {
        resolve({
          token: 'admin-token-123456',
          userInfo: { name: '管理员' },
          roles: ['admin'],
          permissions: ['user:manage', 'order:view', 'setting:edit']
        })
      } else {
        resolve({
          token: 'user-token-123456',
          userInfo: { name: '普通用户' },
          roles: ['user'],
          permissions: ['order:view']
        })
      }
    }, 500)
  })
}

// 登出接口
export function logoutApi() {
  return Promise.resolve()
}

五、3. 路由配置 + 全局权限守卫

src/router/index.js

javascript 复制代码
import { createRouter, createWebHistory } from 'vue-router'
import { useUserStore } from '@/stores/user'

const routes = [
  // 无需权限
  { path: '/', component: () => import('@/views/Home.vue') },
  { path: '/login', component: () => import('@/views/Login.vue') },
  { path: '/403', component: () => import('@/views/403.vue') },

  // 需要登录才能访问
  {
    path: '/user-center',
    component: () => import('@/views/UserCenter.vue'),
    meta: { requiresAuth: true }
  },

  // 必须是 admin 角色才能访问
  {
    path: '/admin',
    component: () => import('@/views/Admin.vue'),
    meta: { requiresAuth: true, role: 'admin' }
  },

  // 必须拥有某个权限码才能访问
  {
    path: '/user-manage',
    component: () => import('@/views/UserManage.vue'),
    meta: { requiresAuth: true, permission: 'user:manage' }
  }
]

const router = createRouter({
  history: createWebHistory(),
  routes
})

// 全局权限守卫(核心)
router.beforeEach((to, from, next) => {
  const userStore = useUserStore()
  const hasToken = !!userStore.token

  // 1. 不需要权限 → 直接放行
  if (!to.meta.requiresAuth) return next()

  // 2. 需要权限,但未登录 → 跳登录
  if (!hasToken) return next('/login')

  // 3. 校验角色(页面指定了角色才校验)
  if (to.meta.role && !userStore.roles.includes(to.meta.role)) {
    return next('/403')
  }

  // 4. 校验权限码(细粒度控制)
  if (to.meta.permission && !userStore.permissions.includes(to.meta.permission)) {
    return next('/403')
  }

  // 5. 全部校验通过
  next()
})

export default router

六、4. 挂载 Pinia 到 main.js

src/main.js

javascript 复制代码
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'

const pinia = createPinia()
pinia.use(piniaPluginPersistedstate) // 持久化

createApp(App)
  .use(pinia)
  .use(router)
  .mount('#app')

七、5. 登录页面示例(可直接用)

src/views/Login.vue

vue 复制代码
<template>
  <div>
    <h2>登录</h2>
    <input v-model="loginForm.username" placeholder="输入 admin 或 user" />
    <input v-model="loginForm.password" placeholder="密码随便输" />
    <button @click="handleLogin">登录</button>
  </div>
</template>

<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
import { useUserStore } from '@/stores/user'

const router = useRouter()
const userStore = useUserStore()

const loginForm = ref({
  username: '',
  password: ''
})

// 登录
const handleLogin = async () => {
  await userStore.login(loginForm.value)
  router.push('/') // 登录成功跳首页
}
</script>

八、6. 403 无权限页面

src/views/403.vue

vue 复制代码
<template>
  <div style="text-align:center; margin-top:100px;">
    <h1>❌ 无权限访问</h1>
    <p>你没有权限查看该页面</p>
    <button @click="$router.back()">返回上一页</button>
  </div>
</template>

九、7. 登出按钮(任意页面使用)

vue 复制代码
<script setup>
import { useUserStore } from '@/stores/user'
import { useRouter } from 'vue-router'

const userStore = useUserStore()
const router = useRouter()

const handleLogout = async () => {
  await userStore.logout()
  router.push('/login')
}
</script>

<template>
  <button @click="handleLogout">退出登录</button>
</template>

十、你可以直接用的 3 种权限配置

1)只要登录就能进

javascript 复制代码
meta: { requiresAuth: true }

2)必须是管理员角色

javascript 复制代码
meta: { requiresAuth: true, role: 'admin' }

3)必须拥有某个权限码

javascript 复制代码
meta: { requiresAuth: true, permission: 'user:manage' }

十一、这套系统的优势

  • ✅ 刷新页面权限不丢失
  • ✅ 登录自动获取权限
  • ✅ 路由统一控制,不用每个页面写判断
  • ✅ 支持角色 + 权限码双重控制
  • ✅ 轻量、企业标准方案

十二、 总结

我已经把 Pinia 状态管理 + 登录接口 + 权限持久化 + 路由守卫 全部整合完毕,你直接复制到项目即可运行,不需要再改任何逻辑。

相关推荐
还是大剑师兰特1 天前
地图的分类
大剑师·地图分类
还是大剑师兰特12 天前
ruoyi‑vue3 添加【车辆管理】菜单组完整方案
大剑师·若依系统
还是大剑师兰特15 天前
若依(ruoyi)前后台系统从零到一部署配置(坑点带解析)
大剑师
还是大剑师兰特16 天前
ideaIC‑2024.1.7(社区版zip绿色解压版)完整使用教程
大剑师·idealc
还是大剑师兰特18 天前
MySQL8.0 Windows完整安装教程
windows·mysql·大剑师
还是大剑师兰特2 个月前
VSCode 插件冲突导致崩溃、卡死、假死 全套根治方案
vscode·大剑师
还是大剑师兰特2 个月前
ThinkPad T490 Windows 自动修复失败完整解决步骤
windows·大剑师·t490
还是大剑师兰特2 个月前
二年级奥数(12) : 巧填符号+竖式数字谜
大剑师·二年级奥数
还是大剑师兰特2 个月前
二年级奥数(9):鸡兔同笼+ 归一问题
大剑师·二年级奥数
还是大剑师兰特2 个月前
二年级奥数(7):移多补少8题 + 和差入门8题 + 年龄问题8题
大剑师·二年级奥数