Vue.js基于角色的登录与权限控制实现方案咨询
基于角色的登录重定向与权限配置方案(Vue.js)
问题背景
我是Vue.js初学者,正在开发一个包含基于角色的登录和报表列表功能的项目,设计了HAuser和Supplier两类角色,需要实现:
- 不同角色用户登录后自动跳转到对应页面
- 配置差异化的页面访问权限
- 报表列表根据角色过滤展示
已完成的代码实现
登录组件
<template> <div class="auth-inner"> <h3>{{ userType }} {{ $t('Login') }}</h3> <form v-on:submit.prevent="onSubmit"> <div class="form-group"> <label>{{ $t('username') }}</label> <input v-model="loginForm.username" type="username" class="form-control" :placeholder="$t('username')" /> </div> <div class="form-group"> <label>{{ $t('password') }}</label> <input v-model="loginForm.password" type="password" class="form-control" :placeholder="$t('password')" /> </div> <div class="d-grid gap-2"> <button class="btn btn-primary" type="submit">{{ $t('Login') }}</button> <vue-recaptcha ref="recaptcha" @verify="onCaptchaVerified" @expired="onCaptchaExpired" sitekey="6LfCmnEhAAAAAIsEHJx8QXbUHIAvIsuuwQW4JGj_" class="mt-3" /> </div> <div v-if="showErrorMessage" class="recaptcha-error-message"><strong>{{ $t('recaptcha-error-message') }}</strong></div> </form> </div> </template> <script> import { VueRecaptcha } from 'vue-recaptcha'; export default { name: 'login', props: ['userType'], components: { VueRecaptcha }, data(){ return{ showErrorMessage: false, recaptchaToken: '', status: '', sucessfulServerResponse: '', serverError: '', recaptchaVerified: false, submitted: false, loading: false, returnUrl: '', error: '', loginForm: { username: '', password: '', } } }, methods: { onCaptchaVerified: function (recaptchaToken) { this.showErrorMessage = false; this.loginForm.recaptchaVerified = true; this.recaptchaToken = recaptchaToken; }, onCaptchaExpired: function () { this.loginForm.recaptchaVerified = false; this.$refs.recaptcha.reset(); if (!this.loginForm.recaptchaVerified) { this.showErrorMessage = true; return; // 阻止表单提交 } }, onSubmit () { if (!this.loginForm.recaptchaVerified) { this.showErrorMessage = true; return; // 阻止表单提交 } } } } </script> <style> .recaptcha-error-message { color: red; } .auth-inner { width: 450px; margin:auto; background: #ffffff; box-shadow: 0px 14px 80px rgba(34, 35, 58,0.2); padding: 40px 55px 45px 55px; border-radius: 15px; transition: all .3s; } </style>
不同用户视图
HAuser视图
<template> <Login userType='HAuser'/> </template> <script> import Login from '@/components/Login.vue'; export default { components: { Login } } </script> <style> </style>
Supplier视图
<template> <Login userType='Supplier' /> </template> <script> import Login from '@/components/Login.vue'; export default { components: { Login }, } </script> <style> </style>
报表常量
{ "reports": [ { "type": "Supplier", "name": "Summary of Users Last Access Time" }, { "type": "Supplier", "name": "Capital Budget Report - Grand Summary" }, { "type": "HAuser", "name": "(Workflow) Report on Site Directions/Memo Status" }, { "type": "HAuser", "name": "Yearly Budget Forecast Working Sheet by Project" }, { "type": "HAuser", "name": "Report on SWD's Lotteries Fund Project Under Block" } ] }
解决方案
一、完善登录逻辑与登录后重定向
在登录组件的onSubmit方法中完成登录请求,获取后端返回的用户角色并存储,再根据角色跳转对应页面:
<script> import { VueRecaptcha } from 'vue-recaptcha'; export default { // 保留原有代码 methods: { // 保留原有验证码方法 async onSubmit () { if (!this.loginForm.recaptchaVerified) { this.showErrorMessage = true; return; } this.loading = true; try { // 发送登录请求,携带用户名、密码、验证码及角色类型 const response = await this.$axios.post('/api/login', { ...this.loginForm, userType: this.userType, recaptchaToken: this.recaptchaToken }); const { userInfo, token } = response.data; // 存储用户信息到localStorage(推荐用Vuex+持久化插件替代) localStorage.setItem('user', JSON.stringify(userInfo)); localStorage.setItem('token', token); // 根据角色重定向到对应首页 if (userInfo.role === 'HAuser') { this.$router.push('/hauser-dashboard'); } else if (userInfo.role === 'Supplier') { this.$router.push('/supplier-dashboard'); } } catch (err) { this.error = err.response?.data?.message || '登录失败'; } finally { this.loading = false; } } } } </script>
二、配置路由权限控制
通过Vue Router的全局导航守卫拦截路由,校验用户角色权限:
1. 定义带权限的路由规则
在router/index.js中配置路由,给需要权限的页面添加meta.roles字段:
import Vue from 'vue'; import VueRouter from 'vue-router'; import HAuserDashboard from '@/views/HAuserDashboard.vue'; import SupplierDashboard from '@/views/SupplierDashboard.vue'; import HAuserLogin from '@/views/HAuserLogin.vue'; import SupplierLogin from '@/views/SupplierLogin.vue'; import ReportList from '@/views/ReportList.vue'; import NotFound from '@/views/NotFound.vue'; import Forbidden from '@/views/Forbidden.vue'; Vue.use(VueRouter); const routes = [ { path: '/hauser-login', component: HAuserLogin }, { path: '/supplier-login', component: SupplierLogin }, // HAuser专属页面 { path: '/hauser-dashboard', component: HAuserDashboard, meta: { roles: ['HAuser'], requiresAuth: true } }, // Supplier专属页面 { path: '/supplier-dashboard', component: SupplierDashboard, meta: { roles: ['Supplier'], requiresAuth: true } }, // 报表列表页面(双角色可访问,内容差异化) { path: '/reports', component: ReportList, meta: { roles: ['HAuser', 'Supplier'], requiresAuth: true } }, { path: '/403', component: Forbidden }, { path: '*', component: NotFound } ]; const router = new VueRouter({ routes }); export default router;
2. 添加全局导航守卫
在router/index.js末尾添加权限校验逻辑:
router.beforeEach((to, from, next) => { // 无需权限的页面直接放行 if (!to.meta.requiresAuth) { next(); return; } // 检查用户是否已登录 const user = JSON.parse(localStorage.getItem('user')); if (!user) { // 未登录跳转到对应角色登录页(可改为登录选择页) next('/hauser-login'); return; } // 校验角色权限 if (to.meta.roles.includes(user.role)) { next(); } else { // 无权限跳转至403页面 next('/403'); } });
三、报表列表按角色过滤展示
在报表列表组件中,根据当前用户角色过滤报表数据:
<template> <div class="report-list"> <h2>我的报表</h2> <ul> <li v-for="report in filteredReports" :key="report.name" class="report-item"> {{ report.name }} </li> </ul> </div> </template> <script> import reportsData from '@/constants/reports.json'; export default { data() { return { allReports: reportsData.reports }; }, computed: { filteredReports() { const user = JSON.parse(localStorage.getItem('user')); // 过滤出当前角色对应的报表 return this.allReports.filter(report => report.type === user.role); } } }; </script> <style scoped> .report-item { padding: 10px; border-bottom: 1px solid #eee; } </style>
四、优化建议
- 用Vuex管理用户状态:替代localStorage,配合
vuex-persistedstate插件实现状态持久化,便于全局调用用户信息。 - 添加退出登录逻辑:清除存储的用户信息和token,跳转至登录页。
- 统一错误处理:对登录失败、权限校验失败等场景添加友好提示。
内容的提问来源于stack exchange,提问作者ka hei tong
相关产品推荐
相关产品推荐

