## 權限控制
#### 前端權限控制
在商城運營時,我們可能是多個人員共同操作我們的系統,但是每個操作人員所具備的權限應該不同,權限的不同主要表現在兩個部分,即導航菜單的查看權限和頁面增刪改操作按鈕的操作權限。我們的把頁面導航菜單查看權限和頁面操作按鈕統一存儲在菜單數據庫表中,菜單類型頁面資源的類型。類型包括目錄 、菜單 、按鈕。
#### 權限標識
權限標識用來進行權限控制的唯一標識,主要是進行增刪改查的權限控制。
權限標識包括:新增 編輯 刪除 查看等,格式結構類似**xxx:xxx:xxx** 如:**admin:user:update**。
#### 導航菜單權限流程
用戶登錄之后,跳轉至首頁,前端發送請求到后臺獲取該用戶下的所有菜單權限與認證權限數據,認證權限為約束用戶增刪改查操作,在路由導航守衛路由時加載用戶導航菜單并存儲到本地存儲中。導航欄從本地存儲讀取菜單列表并進行渲染。
#### 頁面按鈕權限實現
用戶登錄系統之后,跳轉到首頁,在路由導航守衛路由時加載用戶權限標識集合。返回結果是用戶權限標識的集合,頁面操作按鈕提供權限標識,查詢該權限標識是否在用戶權限標識集合中,如有存在,則將按鈕為可見狀態,如不存在,則將按鈕為不可見狀態,根據需求,也可以設置成禁用狀態。
#### 加載導航菜單權限與頁面按鈕權限數據
##### 動態路由與導航欄
在`router/index.js`中,從后臺加載導航菜單、頁面按鈕權限數據,并將數據保存到本地存儲中,如下所示:
```javascript
router.beforeEach((to, from, next) => {
// 添加動態(菜單)路由
if (router.options.isAddDynamicMenuRoutes || fnCurrentRouteType(to, globalRoutes) === 'global') {
next()
} else {
http({
url: http.adornUrl('/sys/menu/nav'),
method: 'get',
params: http.adornParams()
}).then(({ data }) => {
sessionStorage.setItem('authorities', JSON.stringify(data.authorities || '[]'))
fnAddDynamicMenuRoutes(data.menuList)
router.options.isAddDynamicMenuRoutes = true
sessionStorage.setItem('menuList', JSON.stringify(data.menuList || '[]'))
next({ ...to, replace: true })
}).catch((e) => {
console.log(`%c${e} 請求菜單列表和權限失敗,跳轉至登錄頁!!`, 'color:blue')
router.push({ name: 'login' })
})
}
})
```
通過`fnAddDynamicMenuRoutes()`方法,動態加載菜單到路由中保存到本地存儲`sessionStorage`中。但是現在只有路由,還需要將導航欄展示出來。在`main-sidebar.vue`中,我們將本地存儲中菜單數據取出來,然后對導航欄動態渲染出來,并通過**menuId**與動態(菜單)路由進行匹配跳轉至指定路由,這樣,當我們點擊菜單的時候,就會跳轉至特定的路由。
```javascript
created () {
this.menuList = JSON.parse(sessionStorage.getItem('menuList') || '[]')
this.dynamicMenuRoutes = JSON.parse(sessionStorage.getItem('dynamicMenuRoutes') || '[]')
this.routeHandle(this.$route)
}
<sub-menu v-for="menu in menuList"
:key="menu.menuId"
:menu="menu"
:dynamicMenuRoutes="dynamicMenuRoutes">
</sub-menu>
```
`sub-menu`組件的部分代碼
```html
<template>
<el-submenu
v-if="menu.list && menu.list.length >= 1"
:index="menu.menuId + ''"
:popper-class="'site-sidebar--' + sidebarLayoutSkin + '-popper'">
<template slot="title">
<icon-svg :name="menu.icon || ''" class="site-sidebar__menu-icon"></icon-svg>
<span>{{ menu.name }}</span>
</template>
<sub-menu
v-for="item in menu.list"
:key="item.menuId"
:menu="item"
:dynamicMenuRoutes="dynamicMenuRoutes">
</sub-menu>
</el-submenu>
<el-menu-item v-else :index="menu.menuId + ''" @click="gotoRouteHandle(menu)">
<icon-svg :name="menu.icon || ''" class="site-sidebar__menu-icon"></icon-svg>
<span>{{ menu.name }}</span>
</el-menu-item>
</template>
```
##### 按鈕權限
在組件中根據外部方法傳入的權限標識進行權限判斷,如果權限存在,則顯示為可見狀態,否則不可見。
```html
<el-button type="primary"
icon="el-icon-plus"
size="small"
v-if="isAuth('admin:indexImg:save')"
@click.stop="addOrUpdateHandle()">新增</el-button>
```
通過`isAuth(“權限標識”)`,判斷按鈕是否有相同的標識,如果有則可見,否則不可見
```javascript
/**
* 是否有權限
* @param {*} key
*/
export function isAuth (key) {
let authorities = JSON.parse(sessionStorage.getItem('authorities') || '[]')
if (authorities.length) {
for (const i in authorities) {
const element = authorities[i]
if (element.authority === key) {
return true
}
}
}
return false
}
```
注:后臺通過`@PreAuthorize("@pms.hasPermission('admin:user:update')")`來定義請求所需要的權限,如果用戶沒有該權限,后臺就會拋出401未授權狀態碼,前端捕獲到該狀態碼后,會登出當前的賬號,讓用戶重新登陸。

#### 后臺菜單管理、角色管理與管理員列表
##### 菜單管理
在【系統管理】-【菜單管理】中,我們可以通過類配置的方式,更直觀的對菜單列表增刪改查進行管理。
菜單類型包括目錄 、菜單 、按鈕。
目錄為導航欄的大的分類,菜單為分類下的每一項,每個菜單需要綁定上級及填寫對應跳轉的路由,路由路徑對應工程的目錄如下圖:

在新增按鈕權限時,注意授權標識要與后臺一致,新增完之后需要重啟刷新生效。


##### 角色管理
在【系統管理】-【角色管理】中,管理員可以新增角色,并且賦予該角色可以訪問的權限項。

##### 管理員管理
在【系統管理】- 【管理員列表】中,擁有該權限的管理員可以對其進行管理,該管理員可添加或修改管理權限,并可分配列表中的用戶角色。

- 開發環境準備
- 基本開發手冊
- 項目目錄結構
- 權限管理
- 通用分頁表格
- Swagger文檔
- undertow容器
- 對xss攻擊的防御
- 分布式鎖
- 統一的系統日志
- 統一驗證
- 統一異常處理
- 文件上傳下載
- 一對多、多對多分頁
- 認證與授權
- 從授權開始看源碼
- 自己寫個授權的方法-開源版
- 商城表設計
- 商品信息
- 商品分組
- 購物車
- 訂單
- 地區管理
- 運費模板
- 接口設計
- 必讀
- 購物車的設計
- 訂單設計-確認訂單
- 訂單設計-提交訂單
- 訂單設計-支付
- 生產環境
- nginx安裝與跨域配置
- 安裝mysql
- 安裝redis
- 傳統方式部署項目
- docker
- 使用docker部署商城
- centos jdk安裝
- docker centos 安裝
- Docker Compose 安裝與卸載
- docker 鏡像的基本操作
- docker 容器的基本操作
- 通過yum安裝maven
- 常見問題