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 天前
Pinia在Vue3中的应用部署与使用,包括持久化方案
pinia·大剑师
还是大剑师兰特2 天前
Vue3 全局公共函数完整方案(创建、挂载、引用、使用)
大剑师·全局函数
还是大剑师兰特3 天前
vue3 hooks文件夹中文件类型、命名规范、引用方式
大剑师
还是大剑师兰特4 天前
.pnpm-store作用是什么,可以删除吗?
大剑师·pnpm-store
还是大剑师兰特3 个月前
拥抱AI,还是大剑师兰特2025年博客创作详细总结
人工智能·大剑师·2025博客之星
还是大剑师兰特3 个月前
SVG图像文件结构
大剑师·svg图像
还是大剑师兰特3 个月前
JEPG图像文件结构
大剑师·jepg结构
还是大剑师兰特3 个月前
GIF图像文件结构
大剑师·gif图像结构
还是大剑师兰特3 个月前
PNG图像文件结构
服务器·大剑师·png结构