管理系統之權限的設計和實現

本文主要想對前端權限管理功能實現作一個分享,因此並不會對後臺管理的框架結構作太詳細介紹,若是有朋友對其餘有興趣能夠留言。前端

基本設計和分析

  • 前端 vue + elementui
  • 服務端: node + mysql + nginx

主要功能

打開思否頁面,根據頁面的功能點,設計出相關的數據表,和管理系統須要的相關頁面。
計劃後臺管理須要完成的功能:vue

  • 權限管理(菜單權限到數據權限) -- 已完成
  • 工做流 (問答和文章在某個條件內,提交須要走流程)-- 未完成
  • socket (對用戶點贊,評論,系統通知等消息進行實時推送)-- 未完成
  • 文件管理(將頁面須要用到的文件上傳管理,其餘頁面都統一訪問文件庫資源)-- 已完成
  • 基本業務 (業務頁面)-- 部分完成

模塊相關介紹

模塊 功能 頁面編碼 描述
登陸 登陸 login 菜單中不顯示
401 401 401 角色無訪問權限時進入這個頁面
404 404 404 訪問菜單不存在時進入這個頁面
首頁 首頁 home
運維中心 opsCenter
- 問答管理 questionMan
- 專欄管理 blogMan
- 文章管理 articleMan
- 講堂管理 liveMan
- 活動管理 activityMan
- 廣告位 advertising
工做流 workflow
- 流程設計 processDesign
- 業務管理 businessMan
- 已辦事項 finishedItems
- 未辦事項 unfinishedItems
文件庫 library
- 圖片管理 imgMan
- 文件管理 fileMan
論壇配置 bbsConfig
- 輪播 carousel
- 技術頻道 techSquare
- 通知 notices
- 標籤類型管理 tagTypeMan
- 標籤管理 tagMan
系統管理 sysMan
- 用戶管理 userMan
- 角色管理 roleMan
- 菜單管理 menuMan
- 區域管理 areaMan
- 圖表配置 chartConfig
- 系統日誌 log

代碼結構

├── admin                      // 打包產出文件
├── node_module                // npm加載所需的項目依賴模塊
├── public                     // 靜態入口
├── src                        // 源代碼
│   ├── api                    // 全部請求
│   ├── assets                 // 主題 字體 圖片等靜態資源
│   ├── common                 // 全局公用配置
│   │   ├── config             // 配置全局路由權限和錯誤捕獲
│   │   ├── mixin              // 一些vue公用的mixin
│   │   ├── js                 // 編寫公有的方法
│   │   └── style              // 編寫公有的樣式
│   ├── components             // 全局公用組件
│   ├── directive              // 自定義指令
│   ├── router                 // 路由
│   ├── store                  // 全局 store管理
│   ├── views                  // view
│   ├── App.vue                // 入口頁面
│   └── main.js                // 入口 加載組件 初始化等
├── static                     // 第三方不打包資源
├── .babelrc                   // babel-loader 配置
├── eslintrc.js                // eslint 配置項
├── .gitignore                 // git 忽略項
├── vue.config.js              // vue-cli@3.0+ 配置文件
└── package.json               // package.json

權限設計

進入正文,關於權限設計,圍繞的是前端頁面,可是會將前端和後端的邏輯都講出來。node

用戶管理

建立

clipboard.png

前端頁面

看圖中圈起來的地方,前端看到的邏輯是這樣的:mysql

  • 當前用戶爲admin
  • 樹用右鍵操做admin建立的用戶
  • 樹用右鍵操做建立的用戶admin能夠管理

就是建立了一個用戶,這個用戶建立的用戶以及建立用戶建立的用戶,均可以被當前建立者管理。nginx

接口邏輯
  • 查詢到數據庫中全部的用戶ID
  • 經過用戶ID和建立人ID的關係,經過創建樹狀數據,獲得當前用戶建立的用戶樹
  • 遞歸從用戶樹中獲得全部屬於當前用戶子集的用戶ID
  • select * from table where id in (子集用戶id)

經過這個邏輯,能夠獲得全部當前用戶建立的子集,可是第一步有很大的問題,一旦用戶數量巨大,這樣查詢會很慢。母目前只是爲了功能實現,暫未考慮到性能方面,若是有好的方法,但願指點。git

刪除

clipboard.png

clipboard.png

前端頁面
  1. 刪除用戶,調用接口判斷用戶是否有子集,存在->3,不存在->2
  2. 不存在直接刪除
  3. 存在須要先將當前建立的用戶轉移給其餘用戶(其餘用戶不可爲他的子集)
  4. 將用戶轉移成功,則此時子集爲空 ->2
接口邏輯
  1. 查詢到數據庫中是否存在建立人ID爲當前要刪除的用戶ID
  2. 存在則沒法刪除當前用戶
  3. 前端調用戶轉移接口,將當前用戶建立的用戶轉移給其餘人後,此時可刪除該用戶

菜單管理

菜單設計的時候分爲三個類型,管理平臺,論壇,移動端,可是不必定會寫完,感受一我的寫好累呀~~~~
經過菜單又分還有默認佈局組件和頁面組件的區分,佈局組件爲layout,頁面組件則爲他的子路由,經過嵌套的形式,組成一個完整的頁面。
clipboard.pnggithub

頁面

clipboard.png
目前頁面上都是經過右鍵點擊樹組件,進入操做,如圖所示,能夠對菜單進行增刪改查操做。sql

菜單字段的定義和相關用處
字段定義是這樣的:
看到圖中有這些字段,對主要字段說明:
  • 菜單編碼(對應前端頁面的文件名,好比userMan, 渲染時就會找到 */userMan/index去resolve)
  • 菜單組件 (指的是layout等,後面若是須要作多佈局,經過這個設置頁面便可有不一樣佈局)

clipboard.png

-- ----------------------------
-- bbs_menu
-- ----------------------------
DROP TABLE IF EXISTS `bbs_menu`;
CREATE TABLE `bbs_menu` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `pid` INT(11) DEFAULT '0',
  `type` tinyint(4) NOT NULL DEFAULT '1' COMMENT '菜單類型: 1. 管理平臺菜單 2. BBS菜單 3. 移動端菜單',
  `code` VARCHAR(48) NOT NULL COMMENT '菜單編碼',
  `name` VARCHAR(48) NOT NULL COMMENT '菜單名稱',
  `component` tinyint(4) NOT NULL COMMENT '對應組件: -1. 根節點 1. 頁面組件 2.默認佈局 3456...擴展布局',
  `icon` VARCHAR(128) DEFAULT NULL COMMENT '菜單圖標',
  `alias` VARCHAR(128) DEFAULT NULL COMMENT '別名',
  `redirect` VARCHAR(128) DEFAULT NULL COMMENT '重定向路徑: 配置菜單編碼或URL',
  `sort` INT(11) NOT NULL,
  `desc` VARCHAR(128) DEFAULT NULL,
  `status` tinyint(4) NOT NULL DEFAULT '1' COMMENT '狀態: 0:停用,1:啓用(默認爲1)',
  `create_user` INT(11) DEFAULT NULL,
  `create_time` datetime DEFAULT NULL,
  `update_user` INT(11) DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  `delete_user` INT(11) DEFAULT NULL,
  `delete_time` datetime DEFAULT NULL,
  `flag` tinyint(4) NOT NULL DEFAULT '1' COMMENT '狀態: 0:刪除,1:可用(默認爲1)',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='菜單表';
id: '', // *惟一ID
    pid: '', // *父ID
    type: '', // *菜單類型
    code: '', // *菜單編碼
    name: '', // *菜單名稱
    component: '', // *菜單組件
    icon: '', // 菜單圖標
    redirect: '', // 重定向路徑
    sort: '', // *排序
    desc: '', // 描述
    status: 1 // *狀態: 0:停用,1:啓用(默認爲1)'

有什麼用處呢和好處呢,就我的而言,就是以爲把路由表放在數據庫,讓項目更易於維護,在頁面中經過一個匹配邏輯,能夠將全部字段組裝成爲可使用的路由表:vue-cli

// 獲得頁面路徑
function getPath (arr, child, code) {
  const pItem = arr.find(item => child.pid === item.id)
  // 當前元素還存在父節點, 且父節點不爲根節點
  if (arr.find(item => pItem.pid === item.id && item.pid > -1)) {
    getPath(arr, pItem, `${pItem.code}/${code}`)
  } else {
    return `${pItem.code}/${code}`
  }
}
// 對基礎數據的處理
              item.meta = {}
              item.meta.title = item.name
              item.meta.icon = item.icon
              item.meta.id = item.id
              // 使路由名字具備惟一性
              item.name = item.name + index
              // 設置對應的頁面路徑
              item.path = '/' + item.code
// 設置頁面對應的組件 對應組件: -1. 根節點 1. 頁面組件 2.默認佈局 3456...擴展布局
              switch (item.component) {
                case -1:
                  console.log('根節點,已通過濾掉了')
                  break
                case 1:
                  item.component = resolve => require([`@/views/${getPath(menu, item, item.code)}/index`], resolve)
                  break
                case 2:
                  item.component = Layout
                  break
                default:
                  item.component = resolve => require(['@/views/errorPage/401'], resolve)
                  break
              }

經過這種方式,在設置頁面權限的時候,只須要接口設置當前角色對應的菜單,用戶查詢的時候能獲取到的就是當前分配給他的權限,將這個權限組裝成路由表,便可。數據庫

數據權限

上面說的是菜單的配置,以及生成。而後和每一個頁面相關的數據權限,須要點擊到頁面級別的菜單才能夠訪問到,如圖:

clipboard.png

選中一個菜單以後,能夠對這個菜單添加數據權限的控制,好比添加,編輯,刪除等操做。

數據權限的實現

主要是字段設計,因此對圖中字段(開發人員錄入)詳細說明:

  • 功能編碼 (頁面編碼:功能編碼,主要用於前端控制顯隱)
  • 功能api (接口編碼,後端經過判斷用戶是否存在這個編碼,來判斷是否存在操做權限)
  • 請求方式 (restfulApi狀況下,由於api編碼相同,須要根據請求方式來判斷用戶的操做權限)

clipboard.png

前端實現

分配完權限以後,前端頁面在對應的按鈕或要操做的dom上,經過v-if 功能編碼是否存在來設置操做權限的顯示隱藏。
可是前端的顯隱一旦用戶繞過頁面去訪問接口便可,因此數據權限前端只是操做顯隱,具體實現還在後端。

後端實現
  • 作一個數據權限中間層,用戶訪問時中間層判斷當前訪問的接口用戶是否擁有權限
  • 怎麼判斷,經過前端設置的功能api和請求方式,去表中查詢當前用戶角色是否可訪問
  • 可訪問繼續往下走,不能訪問就拒絕了

角色管理

用戶存在了,菜單和數據權限也配置好了,可是須要角色去將他們關聯到一塊兒。

綁定用戶

這裏設置的邏輯是一個用戶只能綁定一個角色。
角色管理頁面,仍是右鍵樹組件,能夠看到綁定用戶的選項

clipboard.png

clipboard.png

分配權限

一樣是右鍵,能夠開始對角色進行分配權限的操做

clipboard.png

左邊是頁面的權限分配,選中頁面以後,右邊會出現數據權限的分配:

clipboard.png

繼承式的分配權限
  • 總共有100個權限
  • a有50個,a給b分配時,只能分配50個
  • 假設a給b分配了30個,c爲b的下級,d爲c的下級
  • c此時無權限,a或b能分配30個給c,但因爲c無權限,a或b分配給d時,分配的列表爲空

總結

建立用戶
建立菜單
建立角色
用戶綁定角色,角色分配權限
完成

最後

案例地址

node服務

相關文章
相關標籤/搜索