目前java后端主要用的权限认证框架有SpringSecurity、Apache Shiro、Sa-Token这三种,本文主要讲的是SpringSecurity加上前端的自定义权限指令v-permission的简单创建及使用。
仅在后端用SpringSecurity时,分配项目角色的权限时可以发现,给角色分配系统的菜单,不勾选菜单之后角色左侧的菜单路由就不会显示,但是取消勾选按钮后,按钮还是会显示在前端页面中,只是在点击后才会提示“无权限”,那如何使权限范围可以控制到页面上的每一个按钮是否显示?如此精确的范围控制只依赖后端已经难以完成,此时需要前端进行一定的逻辑判断,这里具体讲一下前端做法。
一、创建一个permission.js文件,用于判断用户的权限
/** * 按钮级权限控制 */ import { useUserStore } from '@/store/modules/user'; /* 判断数组是否有某些值 */ function arrayHas(array, value) { if (!value) { return true; } if (!array) { return false; } if (Array.isArray(value)) { for (let i = 0; i < value.length; i++) { if (array.indexOf(value[i]) === -1) { return false; } } return true; } return array.indexOf(value) !== -1; } /* 判断数组是否有任意值 */ function arrayHasAny(array, value) { if (!value) { return true; } if (!array) { return false; } if (Array.isArray(value)) { for (let i = 0; i < value.length; i++) { if (array.indexOf(value[i]) !== -1) { return true; } } return false; } return array.indexOf(value) !== -1; } /** * 是否有某些角色 * @param value 角色字符或字符数组 */ export function hasRole(value) { const userStore = useUserStore(); return arrayHas(userStore?.roles, value); } /** * 是否有任意角色 * @param value 角色字符或字符数组 */ export function hasAnyRole(value) { const userStore = useUserStore(); return arrayHasAny(userStore?.roles, value); } /** * 是否有某些权限 * @param value 权限字符或字符数组 */ export function hasPermission(value) { const userStore = useUserStore(); return arrayHas(userStore?.authorities, value); } /** * 是否有任意权限 * @param value 权限字符或字符数组 */ export function hasAnyPermission(value) { const userStore = useUserStore(); return arrayHasAny(userStore?.authorities, value); } export default { install(app) { // 添加自定义指令 app.directive('role', { mounted: (el, binding) => { if (!hasRole(binding.value)) { el.parentNode?.removeChild(el); } } }); app.directive('any-role', { mounted: (el, binding) => { if (!hasAnyRole(binding.value)) { el.parentNode?.removeChild(el); } } }); app.directive('permission', { mounted: (el, binding) => { if (!hasPermission(binding.value)) { el.parentNode?.removeChild(el); } } }); app.directive('any-permission', { mounted: (el, binding) => { if (!hasAnyPermission(binding.value)) { el.parentNode?.removeChild(el); } } }); } };二、然后在main.js中全局引入这个permission.js。(按需引入,可全局,可局部,这种为全局)
import { createApp } from 'vue'; import App from './App.vue'; import store from './store'; import router from './router'; import permission from './utils/permission'; import i18n from './i18n'; import './styles/index.less'; const app = createApp(App); app.use(store); app.use(router); app.use(permission); app.use(i18n); app.mount('#app');三、使用
<a-button type="primary" class="ele-btn-icon" @click="openAdd()" v- permission="'sys:caidan:add'"> <template #icon> <plus-outlined /> </template> <span >添加</span> </a-button>v-permission里放的时你自定义的按钮权限标识符,此时就能完成权限控制到页面上的每一个按钮是否显示。现在可能会有个疑问,前端有了鉴权后端还需要鉴权吗?
需要!
前端的鉴权只是一个辅助功能,对于专业人员这些限制都是可以轻松绕过的,为保证系统安全:无论前端是否进行了权限校验,后端接口都需要对请求再次进行权限校验!