코드가 너무 보기 흉해서 복사를 권장하지 않습니다. 보편적인 RBAC의 구현 아이디어를 살펴보세요.
git clone https://github.com/wjkang/d2-admin-pm.git
npm install
npm start
백엔드 모의 서비스의 지원이 필요합니다.
git clone https://github.com/wjkang/d2-admin-server.git
npm install
npm start
main.js
에서 created
내용은 router/index.js
로 전달되고 관련 로직이 추가됩니다.
인터페이스 수준 권한 제어를 지원하고 로딩 효과 구성을 지원하도록 axios 관련 코드 plugin/axios/index.js
수정했습니다.
vuex 스토어에 메뉴 모듈을 추가하고 fullAside 를 추가하세요. 전체 경로는 store.state.d2admin.menu.fullAside
입니다.
vuex 스토어에 권한 모듈을 추가하여 사용자의 기능 권한 코드, 역할 코드, 액세스 권한이 있는 인터페이스 및 관리자 ID가 있는지 여부를 저장합니다.
export default {
namespaced : true ,
state : {
//功能编码
functions : [ ] ,
//角色编码
roles : [ ] ,
//接口
interfaces : {
GET : [ ] ,
POST : [ ] ,
PUT : [ ] ,
DELETE : [ ]
} ,
//是否管理员
isAdmin : false
} ,
mutations : {
set ( state , data ) {
state . functions = data . functions ;
state . roles = data . roles ;
state . isAdmin = data . isAdmin ;
state . interfaces = data . interfaces ;
}
}
}
vuex 스토어에 있는 account
모듈의 load
작업 중 다음 부분입니다.
// DB -> store 持久化数据加载上次退出时的多页列表
await dispatch ( 'd2admin/page/openedLoad' , null , { root : true } )
router/index.js
로 이동하여 권한 경로를 로드한 후 실행해야 합니다.
菜单
아래에는 여러功能
이 있을 수 있습니다.菜单
功能
의 permission
필드는 이 메뉴에 액세스하는 데 필요한 기능 권한을 식별합니다 permission
이 기능의 별칭이므로菜单
유형 permission
필드는功能
유형의 하위 노드에 대한 permission
값입니다.permission
필드를 통해 액세스할 수 있는 경로를 필터링합니다. d2admin
의 원래 로그인 로직을 사용하여 글로벌 라우팅 가드는 권한 정보를 가져왔는지 확인하고 권한 정보를 얻은 후에 이를 얻은 것으로 표시합니다.
백엔드가 반환해야 하는 권한 정보에는 권한 필터링 후 설정된 역할 코드, 기능 코드 집합, 인터페이스 정보 집합, 메뉴 목록, 라우팅 목록, 시스템 관리자 식별 여부 등이 포함됩니다. 형식은 다음과 같습니다
{
"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/[email protected]"
}
}
고정 메뉴( /menu/header
, /menu/aside
)를 백엔드에서 반환된 권한 메뉴( accessMenus
)와 병합하고 해당 vuex store 모듈에 저장합니다.
...
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 ] )
라우팅 처리 방법 및 차이점은 추후 관련 글을 참고하시기 바랍니다.
역할 코딩 세트, 기능 코딩 세트, 인터페이스 정보 세트, 시스템 관리자 ID가 해당 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
libs/loading.js
있습니다. 필요에 따라 구성할 수도 있습니다. success
의 경우에도 마찬가지입니다. 이 아이디어에 따라 요청 실패 등과 같은 다른 기능을 직접 구성할 수 있습니다.
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.js
frameIn
에 배치됩니다.
권한 제어가 필요한 메뉴 및 경로 name
path
name
하는 경우에만 메뉴 path
가 일치하는지 확인하세요. keep-alive
적용됩니다. 경로의 component
routerMapCompnonents/index.js
.
개발 단계에서 추가되는 메뉴 및 경로는 개발자가 직접 관리할 수 있으며, 온라인에 접속한 후 해당 목록을 관련자에게 넘겨 유지 관리할 수 있습니다.
문제가 있고 백엔드에서 메뉴와 경로가 반환되는 것을 원하지 않는 경우 프런트엔드에서 메뉴와 경로를 유지 관리할 수 있습니다(경로의
component
여전히 문자열을 사용합니다.mock/permissionMenuAndRouter.js
참조). 메뉴 및 경로 코딩에 대한 해당 권한은 일반적으로 기능 코딩을 사용합니다. 백엔드는 메뉴 및 라우팅 정보를 반환할 필요가 없지만 역할 코딩, 기능 코딩 등과 같은 기타 권한 정보는 여전히 필요합니다. 백엔드에서 반환된 기능 코드 목록을 통해 사용자에게 권한이 있는 메뉴와 경로가 프런트엔드에서 필터링됩니다. 필터링된 메뉴와 경로의 형식은 이전에 백엔드에서 반환된 형식과 일치하며, 처리된 메뉴는 다음과 같습니다. 경로는 백엔드로 사용됩니다. 클라이언트에서 반환된 것과 동일하게 처리하면 됩니다.
Data mock은lazy-mock에서 수정된 d2-admin-server를 사용합니다. 데이터는 실제로 백엔드에서 제공됩니다. 다른 도구와 비교하여 데이터 지속성을 지원하며 데이터베이스를 설치할 필요가 없습니다. 간단한 구성으로 추가, 삭제, 수정 및 쿼리를 위한 인터페이스를 자동으로 생성할 수 있습니다. 자세한 사용법은 게으른 모의 문서를 참조하세요.
백엔드는 미들웨어를 사용하여 다음과 같은 액세스 권한을 제어합니다.
. get ( '/menu' , PermissionCheck ( ) , controllers . menu . getMenuList )
PermissionCheck
기본적으로 확인용 인터페이스를 사용하여 사용자가 액세스할 수 있는 API가 현재 API와 일치하는지 확인합니다. PermissionCheck(["p_menu_edit"],["r_menu_admin"],true)
, 1장 매개변수는 기능 코드, 두 번째는 역할 코드, 세 번째는 검증을 위해 인터페이스를 사용할지 여부입니다.
프론트엔드 코드 생성은 아직 개발 중입니다...
Vue 권한 라우팅 구현 방법 요약 Vue 권한 라우팅 구현 방법 요약 2. 기업 관리 시스템 프런트엔드 및 백엔드 분리 아키텍처 설계 시리즈 1. 권한 모델