自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

權(quán)限想要細(xì)化到按鈕,怎么做?

開發(fā) 項(xiàng)目管理
如果有小伙伴們做過前后端不分的開發(fā),應(yīng)該會(huì)有這樣的體會(huì):在 Shiro 或者 Spring Security 框架中,都提供了一些標(biāo)簽,通過這些標(biāo)簽可以做到在滿足某種角色或者權(quán)限的情況下,顯示某個(gè)按鈕;當(dāng)用戶不具備某種角色或者權(quán)限的時(shí)候,按鈕則會(huì)自動(dòng)隱藏起來。

因?yàn)閷懥瞬簧?Spring Security 文章的緣故,所以總是有小伙伴來問松哥:按鈕級(jí)別的權(quán)限怎么實(shí)現(xiàn)?甚至有一些看過 vhr 的小伙伴也問這種問題,其實(shí)有的時(shí)候搞得我確實(shí)挺郁悶的,最近剛好要做 TienChin 項(xiàng)目,我就再把這個(gè)問題拎出來和小伙伴們仔細(xì)捋一捋。

1. 權(quán)限顆粒度

首先小伙伴們都知道權(quán)限有不同的顆粒度,在 vhr 項(xiàng)目中,整體上我是基于請(qǐng)求地址去處理權(quán)限的,這個(gè)粒度算粗還是算細(xì)呢?

有的小伙伴們可能認(rèn)為這個(gè)權(quán)限粒度太粗,所謂細(xì)粒度的權(quán)限應(yīng)該是基于按鈕的。

如果有小伙伴們做過前后端不分的開發(fā),應(yīng)該會(huì)有這樣的體會(huì):在 Shiro 或者 Spring Security 框架中,都提供了一些標(biāo)簽,通過這些標(biāo)簽可以做到在滿足某種角色或者權(quán)限的情況下,顯示某個(gè)按鈕;當(dāng)用戶不具備某種角色或者權(quán)限的時(shí)候,按鈕則會(huì)自動(dòng)隱藏起來。

但是大家想想,按鈕的顯示與隱藏不過是前端頁面為了提高用戶體驗(yàn)而作出的樣式的變化而已,本質(zhì)上,當(dāng)你點(diǎn)擊一個(gè)按鈕的時(shí)候,還是發(fā)送了一個(gè) HTTP 請(qǐng)求,那么服務(wù)端處理該請(qǐng)求的接口,必須要進(jìn)行權(quán)限控制。既然要在接口上進(jìn)行權(quán)限控制,那么跟 vhr 的區(qū)別在哪里呢?

現(xiàn)在流行前后端分離開發(fā),所以 Shiro 或者 Spring Security 中的那些前端標(biāo)簽現(xiàn)在基本上都不用了,取而代之的做法是用戶在登錄成功之后,向服務(wù)端發(fā)送請(qǐng)求,獲取當(dāng)前登錄用戶的權(quán)限以及角色信息,然后根據(jù)這些權(quán)限、角色等信息,在前端自動(dòng)的去判斷一個(gè)菜單或者按鈕應(yīng)該是顯示還是隱藏,這么做的目的是為了提高用戶體驗(yàn),避免用戶點(diǎn)擊一個(gè)沒有權(quán)限的按鈕。前端的顯示或者隱藏僅僅只是為了提高用戶體驗(yàn),真正的權(quán)限控制還是要后端來做。

后端可以在接口或者業(yè)務(wù)層對(duì)權(quán)限進(jìn)行處理,具體在哪里做,就要看各自的項(xiàng)目了。

所以,vhr 中的權(quán)限,從設(shè)計(jì)上來說,粒度并不算粗,也是細(xì)粒度的,只不過跟菜單表放在了一起,小伙伴們可能感覺有點(diǎn)粗。但是,菜單表是可以繼續(xù)細(xì)化的,我們可以繼續(xù)在菜單表中添加新的記錄,新記錄的 hidden 字段為 true,則菜單是隱藏的,就單純只是細(xì)化權(quán)限而已。

如下圖可以繼續(xù)添加新的訪問規(guī)則,只不過把 enabled 字段設(shè)置為 false 即可(這樣菜單就不會(huì)顯示出來了,單純就只是權(quán)限的配置)。

圖片

所以 vhr 的權(quán)限設(shè)計(jì)是 OK 的。

當(dāng)你理解了 vhr 中的權(quán)限設(shè)計(jì),再來看 TienChin 這個(gè)項(xiàng)目,或者說看 RuoYi-Vue 這個(gè)腳手架,就會(huì)發(fā)現(xiàn)非常 easy 了。

2. 權(quán)限表

首先我們來看看資源表的定義,也就是 sys_menu。

CREATE TABLE `sys_menu` (
`menu_id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '菜單ID',
`menu_name` varchar(50) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '菜單名稱',
`parent_id` bigint(20) DEFAULT '0' COMMENT '父菜單ID',
`order_num` int(4) DEFAULT '0' COMMENT '顯示順序',
`path` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '路由地址',
`component` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '組件路徑',
`query` varchar(255) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '路由參數(shù)',
`is_frame` int(1) DEFAULT '1' COMMENT '是否為外鏈(0是 1否)',
`is_cache` int(1) DEFAULT '0' COMMENT '是否緩存(0緩存 1不緩存)',
`menu_type` char(1) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '菜單類型(M目錄 C菜單 F按鈕)',
`visible` char(1) COLLATE utf8mb4_unicode_ci DEFAULT '0' COMMENT '菜單狀態(tài)(0顯示 1隱藏)',
`status` char(1) COLLATE utf8mb4_unicode_ci DEFAULT '0' COMMENT '菜單狀態(tài)(0正常 1停用)',
`perms` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '權(quán)限標(biāo)識(shí)',
`icon` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT '#' COMMENT '菜單圖標(biāo)',
`create_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '創(chuàng)建者',
`create_time` datetime DEFAULT NULL COMMENT '創(chuàng)建時(shí)間',
`update_by` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '更新者',
`update_time` datetime DEFAULT NULL COMMENT '更新時(shí)間',
`remark` varchar(500) COLLATE utf8mb4_unicode_ci DEFAULT '' COMMENT '備注',
PRIMARY KEY (`menu_id`)
) ENGINE=InnoDB AUTO_INCREMENT=3054 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='菜單權(quán)限表';

其實(shí)這里很多字段都和我們 vhr 項(xiàng)目項(xiàng)目很相似,我也就不重復(fù)啰嗦了,我這里主要和小伙伴們說一個(gè)字段,那就是 menu_type。

menu_type 表示一個(gè)菜單字段的類型,一個(gè)菜單有三種類型,分別是目錄(M)、菜單(C)以及按鈕(F)。這里所說的目錄,相當(dāng)于我們?cè)?vhr 中所說的一級(jí)菜單,菜單相當(dāng)于我們?cè)?vhr 中所說的二級(jí)菜單。

當(dāng)用戶從前端登錄成功后,要去動(dòng)態(tài)加載的菜單的時(shí)候,就查詢 M 和 C 類型的數(shù)據(jù)即可,F(xiàn) 類型的數(shù)據(jù)不是菜單項(xiàng),查詢的時(shí)候直接過濾掉即可,通過 menu_type 這個(gè)字段可以輕松的過濾掉 F 類型的數(shù)據(jù)。小伙伴們想想,F(xiàn) 類型的數(shù)據(jù)過濾掉之后,剩下的數(shù)據(jù)不就是一級(jí)菜單和二級(jí)菜單了,那不就和 vhr 又一樣了么!

最后再來說說 F 類型的,F(xiàn) 類型的就是按鈕級(jí)別的權(quán)限了,前端每一個(gè)按鈕的執(zhí)行,需要哪些權(quán)限,現(xiàn)在就在這里定義好。

舉一個(gè)簡(jiǎn)單的例子大家來看下:

圖片

當(dāng)需要展示用戶管理這個(gè)菜單的時(shí)候,需要 system:user:list? 這個(gè)權(quán)限,當(dāng)需要點(diǎn)擊用戶修改這個(gè)按鈕的時(shí)候,則需要 system:user:edit 這個(gè)權(quán)限。

其他相關(guān)的表基本上和 vhr 都是一樣的,用戶有用戶表 sys_user?,角色有角色表 sys_role?,用戶和角色關(guān)聯(lián)的表是 sys_user_role?,資源和角色關(guān)聯(lián)的表是 sys_role_menu。

當(dāng)用戶登錄成功后,后端會(huì)提供一個(gè)接口,將當(dāng)前用戶的角色和權(quán)限統(tǒng)統(tǒng)返回給前端:

查詢角色思路:根據(jù)用戶 id,先去sys_user_role? 表中查詢到角色 id,再根據(jù)角色 id 去sys_role 表中查詢到對(duì)應(yīng)的角色(這里為了方便大家理解這么描述,實(shí)際上一個(gè)多表聯(lián)合查詢即可)。

查詢權(quán)限思路:根據(jù)用戶 id,先去sys_user_role? 表中查詢到角色 id,再根據(jù)角色 id 去sys_role? 表中查詢到對(duì)應(yīng)的角色,再拿著角色 id 去sys_role_menu? 表中查詢到對(duì)應(yīng)的menu_id?,再根據(jù)menu_id? 去sys_menu 表中查詢到對(duì)應(yīng)的 menu 中的權(quán)限(這里為了方便大家理解這么描述,實(shí)際上一個(gè)多表聯(lián)合查詢即可)。

前端有了用戶的權(quán)限以及角色之后,就可以自行決定是否顯示某一個(gè)菜單或者是否展示某一個(gè)按鈕了。

3. 后端權(quán)限判斷

我先來說說這塊 TienChin 項(xiàng)目中是怎么做的(即 RuoYi 腳手架的實(shí)現(xiàn)方案),再來和 vhr 進(jìn)行一個(gè)對(duì)比。

在 TienChin 項(xiàng)目中是通過注解來控制權(quán)限的,接口的訪問權(quán)限都是通過注解來標(biāo)記的,例如下面這種:

@PreAuthorize("@ss.hasPermi('system:menu:add')")
@PostMapping
public AjaxResult add(@Validated @RequestBody SysMenu menu) {
//省略
}
/**
* 修改菜單
*/
@PreAuthorize("@ss.hasPermi('system:menu:edit')")
@PutMapping
public AjaxResult edit(@Validated @RequestBody SysMenu menu) {
//省略
}
/**
* 刪除菜單
*/
@PreAuthorize("@ss.hasPermi('system:menu:remove')")
@DeleteMapping("/{menuId}")
public AjaxResult remove(@PathVariable("menuId") Long menuId) {
//省略
}

每一個(gè)接口需要什么權(quán)限,都是通過 @PreAuthorize 注解來實(shí)現(xiàn)的。

不過上面這種寫法說到底還是有一點(diǎn)“硬編碼”,因?yàn)樵L問哪個(gè)接口需要哪些權(quán)限,在代碼中固定了,如果接口和權(quán)限直接的關(guān)系能夠保存到數(shù)據(jù)庫中,那么用戶就可以在自己需要的時(shí)候,隨時(shí)進(jìn)行靈活修改,豈不美哉!

在 vhr 項(xiàng)目中,松哥利用 Spring Security 中自定義 FilterInvocationSecurityMetadataSource 和 AccessDecisionManager 實(shí)現(xiàn)了服務(wù)端動(dòng)態(tài)控制權(quán)限。

相對(duì)來說,vhr 中的實(shí)現(xiàn)方案更靈活一些,因?yàn)榭梢耘渲媒涌诤蜋?quán)限之間的關(guān)系。不過怎么說呢?其實(shí)像 RuoYi-Vue 這樣硬編碼其實(shí)也不是不可以,畢竟接口和權(quán)限之間的映射關(guān)系還是稍顯“專業(yè)”一些,普通用戶可能并不懂該如何配置,這個(gè)加入說系統(tǒng)提供了這個(gè)功能,那么更多的還是面向程序員這一類專業(yè)人員的,那么程序員到底是否需要這個(gè)功能呢?我覺得還是得具體情況具體分析。

總之,小伙伴們可以結(jié)合自己項(xiàng)目的實(shí)際情況,來決定接口和權(quán)限之間的映射關(guān)系是否需要?jiǎng)討B(tài)管理,如果需要?jiǎng)討B(tài)管理,那么可以按照 vhr 中的方案來,如果不需要?jiǎng)討B(tài)管理,那么就按照 RuoYi-Vue 腳手架中的方式來就行了。

好啦,這就是 RuoYi-Vue 這個(gè)腳手架中關(guān)于權(quán)限的設(shè)計(jì),現(xiàn)在有一個(gè)新的問題擺在面前:如何給用戶設(shè)置權(quán)限的?現(xiàn)在整個(gè)系統(tǒng)的權(quán)限架構(gòu)師安排的明明白白的,那么用戶的權(quán)限又是從何而來的呢?這個(gè)我們下篇文章繼續(xù)拆解。

責(zé)任編輯:武曉燕 來源: 江南一點(diǎn)雨
相關(guān)推薦

2022-06-27 14:21:09

Spring語言

2022-03-10 11:25:51

InnoDB優(yōu)化

2023-09-27 22:44:18

數(shù)據(jù)遷移數(shù)據(jù)庫

2016-09-21 10:18:26

阿里Dubbo性能測(cè)試

2011-07-05 17:05:15

CIO

2015-10-19 10:30:44

物聯(lián)網(wǎng)營銷

2023-12-14 17:21:28

前端性能優(yōu)化

2023-07-10 15:35:46

2012-05-24 14:58:55

開源代碼

2020-07-28 08:36:54

數(shù)據(jù)安全數(shù)據(jù)泄露數(shù)據(jù)

2020-09-16 08:07:54

權(quán)限粒度Spring Secu

2016-10-27 14:41:45

SaaS企業(yè)SaaS

2018-10-14 16:24:47

工業(yè)物聯(lián)網(wǎng)IIoT物聯(lián)網(wǎng)

2017-07-20 13:11:46

Code ReviewPR評(píng)審

2019-07-02 10:22:15

TCP流量數(shù)據(jù)

2011-03-11 09:53:46

FacebookMySQL

2017-11-08 12:25:37

小程序運(yùn)營公眾號(hào)

2021-05-05 10:48:33

滲透測(cè)試漏洞網(wǎng)絡(luò)攻擊

2013-07-30 17:16:00

產(chǎn)品經(jīng)理

2023-03-03 13:50:55

GPT-3AI
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)