Первые две статьи о маршрутизации разрешений vue заполнили яму и сказали много теорий, пора управлять волной.
Резюме реализации маршрутизации разрешений vue
Сводка реализации маршрутизации разрешений Vue 2
выберитеd2-adminЭто потому, что в связанных проектах с открытым исходным кодом element-ui структура и код d2-admin позволяют мне чувствовать себя наиболее комфортно, а также очень удобно реализовать управление полномочиями RBAC на основе d2-admin, и нет серьезные навязчивые изменения в d2-admin. .
адрес предварительного просмотра
Связанные концепции
Если вы не знаете RBAC, вы можете посмотреть здесьАрхитектура разделения интерфейсов и серверных частей системы управления предприятием Серия 1 Модель разрешений
- Реализован контроль разрешений модели RBAC.
- Меню и маршрутизация управляются независимо и полностью возвращаются серверной частью.
- userхранить пользователя
- adminОпределяет, является ли пользователь системным администратором
- roleХранить информацию о роли
- roleUserХраните ассоциацию между пользователями и ролями
-
menuИнформация о меню магазина, тип
菜单а также功能, в одном меню может быть несколько функций,菜单ТипpermissionПоле определяет функциональное разрешение, необходимое для доступа к этому меню,功能ТипpermissionПоле эквивалентно другому имени этой функции, поэтому菜单Типpermissionполе для одного из功能тип дочернего узлаpermissionстоимость - permissionХраните взаимосвязь между ролями и функциями
- interfaceСохранить информацию об интерфейсе
- functionInterfaceХраните отношения между функциями и интерфейсами.Просматривая роль пользователя, а затем просматривая функциональные разрешения соответствующей роли, а затем через соответствующую функцию, вы можете узнать интерфейсы, к которым пользователь может получить доступ
-
routeХранить информацию о маршрутизации переднего плана через
permissionПоле отфильтровывает маршруты, к которым может получить доступ пользователь.
Запуск процесса и связанный с ним API
использоватьd2adminВ соответствии с исходной логикой входа глобальная защита маршрутизации оценивает, была ли получена информация о разрешении, и после ее получения помечает ее как полученную.
const token = util.cookies.get('token')
if (token && token !== 'undefined') {
//拉取权限信息
if (!isFetchPermissionInfo) {
await fetchPermissionInfo();
isFetchPermissionInfo = true;
next(to.path, true)
} else {
next()
}
} else {
// 将当前预计打开的页面完整地址临时存储 登录后继续跳转
// 这个 cookie(redirect) 会在登录后自动删除
util.cookies.set('redirect', to.fullPath)
// 没有登录的时候跳转到登录界面
next({
name: 'login'
})
}
//标记是否已经拉取权限信息
let isFetchPermissionInfo = false
let fetchPermissionInfo = async () => {
//处理动态添加的路由
const formatRoutes = function (routes) {
routes.forEach(route => {
route.component = routerMapComponents[route.component]
if (route.children) {
formatRoutes(route.children)
}
})
}
try {
let userPermissionInfo = await userService.getUserPermissionInfo()
permissionMenu = userPermissionInfo.accessMenus
permissionRouter = userPermissionInfo.accessRoutes
permission.functions = userPermissionInfo.userPermissions
permission.roles = userPermissionInfo.userRoles
permission.interfaces = util.formatInterfaces(userPermissionInfo.accessInterfaces)
permission.isAdmin = userPermissionInfo.isAdmin == 1
} catch (ex) {
console.log(ex)
}
formatRoutes(permissionRouter)
let allMenuAside = [...menuAside, ...permissionMenu]
let allMenuHeader = [...menuHeader, ...permissionMenu]
//动态添加路由
router.addRoutes(permissionRouter);
// 处理路由 得到每一级的路由设置
store.commit('d2admin/page/init', [...frameInRoutes, ...permissionRouter])
// 设置顶栏菜单
store.commit('d2admin/menu/headerSet', allMenuHeader)
// 设置侧边栏菜单
store.commit('d2admin/menu/fullAsideSet', allMenuAside)
// 初始化菜单搜索功能
store.commit('d2admin/search/init', allMenuHeader)
// 设置权限信息
store.commit('d2admin/permission/set', permission)
// 加载上次退出时的多页列表
store.dispatch('d2admin/page/openedLoad')
await Promise.resolve()
}
Информация о разрешениях, которую серверная часть должна вернуть, включает в себя набор кодов ролей, набор кодов функций, набор информации об интерфейсе, список меню, список маршрутов, а также информацию о том, идентифицирован ли системный администратор после фильтрации разрешений. Формат следующий
{
"statusCode": 200,
"msg": "",
"data": {
"userName": "MenuManager",
"userRoles": [
"R_MENUADMIN"
],
"userPermissions": [
"p_menu_view",
"p_menu_edit",
"p_menu_menu"
],
"accessMenus": [
{
"title": "系统",
"path": "/system",
"icon": "cogs",
"children": [
{
"title": "系统设置",
"icon": "cogs",
"children": [
{
"title": "菜单管理",
"path": "/system/menu",
"icon": "th-list"
}
]
},
{
"title": "组织架构",
"icon": "pie-chart",
"children": [
{
"title": "部门管理",
"icon": "html5"
},
{
"title": "职位管理",
"icon": "opencart"
}
]
}
]
}
],
"accessRoutes": [
{
"name": "System",
"path": "/system",
"component": "layoutHeaderAside",
"componentPath": "layout/header-aside/layout",
"meta": {
"title": "系统设置",
"cache": true
},
"children": [
{
"name": "MenuPage",
"path": "/system/menu",
"component": "menu",
"componentPath": "pages/sys/menu/index",
"meta": {
"title": "菜单管理",
"cache": true
}
},
{
"name": "RoutePage",
"path": "/system/route",
"component": "route",
"componentPath": "pages/sys/route/index",
"meta": {
"title": "路由管理",
"cache": true
}
},
{
"name": "RolePage",
"path": "/system/role",
"component": "role",
"componentPath": "pages/sys/role/index",
"meta": {
"title": "角色管理",
"cache": true
}
},
{
"name": "UserPage",
"path": "/system/user",
"component": "user",
"componentPath": "pages/sys/user/index",
"meta": {
"title": "用户管理",
"cache": true
}
},
{
"name": "InterfacePage",
"path": "/system/interface",
"component": "interface",
"meta": {
"title": "接口管理"
}
}
]
}
],
"accessInterfaces": [
{
"path": "/menu/:id",
"method": "get"
},
{
"path": "/menu",
"method": "get"
},
{
"path": "/menu/save",
"method": "post"
},
{
"path": "/interface/paged",
"method": "get"
}
],
"isAdmin": 0,
"avatarUrl": "https://api.adorable.io/avatars/85/abott@adorable.png"
}
}
меню настроек
закрепит меню (/menu/header,/menu/aside) и меню разрешений, возвращаемое серверной частью (accessMenus) объединяется и сохраняется в соответствующем модуле хранилища vuex.
...
let allMenuAside = [...menuAside, ...permissionMenu]
let allMenuHeader = [...menuHeader, ...permissionMenu]
...
// 设置顶栏菜单
store.commit('d2admin/menu/headerSet', allMenuHeader)
// 设置侧边栏菜单
store.commit('d2admin/menu/fullAsideSet', allMenuAside)
// 初始化菜单搜索功能
store.commit('d2admin/search/init', allMenuHeader)
обрабатывать маршрутизацию
Использовать по умолчаниюrouterMapComponentsспособ обработки маршрута разрешений, возвращаемого серверной частью
//处理动态添加的路由
const formatRoutes = function (routes) {
routes.forEach(route => {
route.component = routerMapComponents[route.component]
if (route.children) {
formatRoutes(route.children)
}
})
}
...
formatRoutes(permissionRouter)
//动态添加路由
router.addRoutes(permissionRouter);
// 处理路由 得到每一级的路由设置
store.commit('d2admin/page/init', [...frameInRoutes, ...permissionRouter])
Методы обработки маршрутизации и различия можно увидетьСводка реализации маршрутизации разрешений Vue 2
Установить информацию о разрешении
Сохраните набор кодов ролей, набор кодов функций, набор информации об интерфейсе и сохраните ли идентификатор системного администратора в соответствующем модуле хранилища vuex.
...
permission.functions = userPermissionInfo.userPermissions
permission.roles = userPermissionInfo.userRoles
permission.interfaces = util.formatInterfaces(userPermissionInfo.accessInterfaces)
permission.isAdmin = userPermissionInfo.isAdmin == 1
...
// 设置权限信息
store.commit('d2admin/permission/set', permission)
Контроль разрешений интерфейса и загрузка конфигурации
Поддержка использования ролевого кодирования, функционального кодирования и разрешений интерфейса для управления следующим образом.
export function getMenuList() {
return request({
url: '/menu',
method: 'get',
interfaceCheck: true,
permission:["p_menu_view"],
loading: {
type: 'loading',
options: {
fullscreen: true,
lock: true,
text: '加载中...',
spinner: 'el-icon-loading',
background: 'rgba(0, 0, 0, 0.8)'
}
},
success: {
type: 'message',
options: {
message: '加载菜单成功',
type: 'success'
}
}
})
}
interfaceCheck: trueУказывает, что разрешения интерфейса используются для управления.Если информация об интерфейсе, хранящаяся в хранилище vuex, соответствует запрашиваемому интерфейсу, запрос может быть инициирован, в противном случае запрос будет перехвачен.
permission:["p_menu_view"]Указывает, что код роли и код функции используются для проверки разрешения.Если код роли или код функции, хранящийся в хранилище vuex, совпадает с кодом, представленным в настоящее время, запрос может быть инициирован, в противном случае запрос будет перехвачен.
Исходный код находится по адресуlibs/permission.js, который может быть изменен в соответствии с вашими потребностями
loadingИсходный код, связанный с конфигурацией, находится вlibs/loading.js, настройте его в соответствии с вашими потребностями,successТо же самое, исходный код находится вlibs/loading.js. Таким образом, вы можете самостоятельно настроить другие функции, например, отказ от запроса.
Управление правами доступа к элементам страницы
инструкции по использованиюv-permission:
<el-button
v-permission:function.all="['p_menu_edit']"
type="primary"
icon="el-icon-edit"
size="mini"
@click="batchEdit"
>批量编辑</el-button>
Параметры могут бытьfunction,role, указывающий, что код функции или код роли используется для проверки, а если он пуст, то оба используются для проверки.
модификаторall, указывая, что все кодировки в значении инструкции должны совпадать.
Исходный код находится по адресуplugin/permission/index.jsи измените его в соответствии с вашими фактическими потребностями.
использоватьv-if+ глобальный метод:
<el-button
v-if="canAdd"
type="primary"
icon="el-icon-circle-plus-outline"
size="mini"
@click="add"
>添加</el-button>
data() {
return {
canAdd: this.hasPermissions(["p_menu_edit"])
};
},
По умолчанию для проверки используются как код роли, так и код функции, и достаточно одного совпадения.
Аналогичный метод такжеhasFunctions,hasRoles.
Исходный код находится по адресуplugin/permission/index.js, и измените его в соответствии с вашими реальными потребностями.
Не используйте
v-if="hasPermissions(['p_menu_edit'])"Таким образом, метод будет выполняться несколько раз.
Вы также можете напрямую прочитать информацию о разрешениях из хранилища vuex в компоненте для проверки.
консультации по развитию
-
Компоненты уровня страницы размещаются в
pages/каталог и вrouterMapCompnonents/index.jsЭкспортируется в виде ключ-значение -
Фиксированные меню, не требующие контроля разрешений, помещаются в
menu/aside.jsа такжеmenu/header.jsсередина -
Маршруты, не требующие контроля разрешений, помещаются в
router/routes.jsframeInВнутри -
Меню и маршруты, требующие контроля разрешений, добавляются через функцию управления интерфейсом, чтобы гарантировать, что меню
pathс маршрутизациейpathСоответственно, маршрутизируетсяnameс компонентами страницыnameбыть последовательнымkeep-aliveэффективный, направленныйcomponentсуществуетrouterMapCompnonents/index.jsможно подобрать по ключу. -
Меню и маршрутизация этапов разработки разработчиками для добавления собственного обслуживания и поддержания списка инвентаризации после линейки соответствующим людям для поддержания может.
Если вы чувствуете себя хлопотно и не хотите, чтобы меню и маршрут возвращались серверной частью, вы можете сохранить меню и маршрут во внешнем интерфейсе (тот, что в маршруте).
componentИли используйте строки, см.mock/permissionMenuAndRouter.js) и поддерживать соответствующие коды разрешений в меню и маршрутах, обычно используя функциональные коды. Серверной части не нужно возвращать информацию о меню и маршрутизации, но по-прежнему требуется другая информация о разрешениях, такая как коды ролей, коды функций и т. д. Через список кодов функций, возвращаемый серверной частью, клиентская часть отфильтровывает меню и маршруты, на которые у пользователя есть разрешения, а формат отфильтрованных меню и маршрутов совпадает с форматом, возвращаемым серверной частью. раньше, а затем обработанные меню и маршруты рассматриваются как бэкэнд, который может обрабатываться так же, как и возвращаемый терминалом.
Имитация данных и генерация кода
Имитация использования данныхlazy-mockмодифицированныйd2-admin-server, данные действительно поступают из серверной части. По сравнению с другими инструментами он поддерживает сохранение данных. Для хранения используются файлы JSON, и нет необходимости устанавливать базу данных. Простая конфигурация может автоматически генерировать интерфейс добавления, удаления, изменения и проверки.
Серверная часть использует промежуточное программное обеспечение для управления правами доступа, например:
.get('/menu', PermissionCheck(), controllers.menu.getMenuList)
PermissionCheckПо умолчанию интерфейс используется для проверки, чтобы убедиться, что API, к которым пользователь может получить доступ, соответствуют текущему API, а код функции и код роли поддерживаются для проверки.PermissionCheck(["p_menu_edit"],["r_menu_admin"],true), Первый параметр — это код функции, второй — код роли, а третий — использовать ли интерфейс для проверки.
Для более подробного использования см.ленивая макетная документация
Генерация внешнего кода все еще находится в разработке...