SpringBoot實(shí)現(xiàn)RBAC權(quán)限校驗(yàn)?zāi)P偷氖纠?/h1>
更新時(shí)間:2025年04月10日 09:38:46 作者:陌路物是人非
本文主要介紹了SpringBoot實(shí)現(xiàn)RBAC權(quán)限校驗(yàn)?zāi)P偷氖纠?文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
最近想做一個(gè)管理系統(tǒng),記錄下自己的消費(fèi)記錄,實(shí)現(xiàn)個(gè)文件上傳之類(lèi)的功能,正好最近看了下RBAC模型,想學(xué)習(xí)一下,在這分享下實(shí)現(xiàn)過(guò)程,方便以后查看
RBAC模型簡(jiǎn)單來(lái)說(shuō)就是創(chuàng)建5張表(用戶(hù)表,角色表,權(quán)限表,角色與用戶(hù)表,角色與權(quán)限表)
通過(guò)給用戶(hù)分配不同角色,以及給角色分配不同權(quán)限,實(shí)現(xiàn)用戶(hù)的權(quán)限控制
不過(guò)這次我做的項(xiàng)目是個(gè)后臺(tái)管理系統(tǒng),主要是自己和朋友使用,所以角色其實(shí)就分成了管理員和普通用戶(hù),因此我省略掉了角色和角色權(quán)限表,這樣雖然不夠靈活,但畢竟使用的人少,所以管理起來(lái)也非常方便
數(shù)據(jù)庫(kù)表
數(shù)據(jù)庫(kù)主要?jiǎng)?chuàng)建三張表
用戶(hù)表:
主要用來(lái)使用用戶(hù)登錄
- id 用戶(hù)主鍵
- account 登錄賬號(hào)
- password 登錄密碼
- type 區(qū)分普通角色和管理員身份
- username 用戶(hù)名
- status 用戶(hù)的狀態(tài)
+-----------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| account | char(15) | YES | | NULL | |
| password | varchar(50) | YES | | NULL | |
| type | int | YES | | NULL | |
| username | varchar(20) | YES | | NULL | |
| status | int | YES | | NULL | |
+-----------+-------------+------+-----+---------+----------------+
權(quán)限表:
主要用來(lái)記錄權(quán)限信息
- id 權(quán)限主鍵
- name 權(quán)限名稱(chēng)
- parent_id 父權(quán)限的id 如果沒(méi)有父權(quán)限則為null
- status 權(quán)限是否啟用
- remark 權(quán)限備注
- level 權(quán)限的層級(jí),主要用來(lái)排序的字段
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| name | varchar(20) | YES | | NULL | |
| parent_id | int | YES | | NULL | |
| status | int | YES | | NULL | |
| remark | varchar(50) | YES | | NULL | |
| create_user | int | YES | | NULL | |
| create_date | date | YES | | NULL | |
| update_user | int | YES | | NULL | |
| update_date | date | YES | | NULL | |
| level | int | YES | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
用戶(hù)權(quán)限表:
實(shí)現(xiàn)多對(duì)多關(guān)系的表
- id 主鍵
- user_id 用戶(hù)的ID
- permission_id 權(quán)限的ID
+---------------+------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+------+------+-----+---------+----------------+
| id | int | NO | PRI | NULL | auto_increment |
| user_id | int | YES | MUL | NULL | |
| permission_id | int | YES | | NULL | |
+---------------+------+------+-----+---------+----------------+
主要解釋下權(quán)限表,因?yàn)楣芾硐到y(tǒng)需要根據(jù)權(quán)限判斷是否提供菜單,因此我將菜單作為了一級(jí)權(quán)限(parent_id=null),一級(jí)權(quán)限下的增刪改查等操作定義為二級(jí)權(quán)限(parent_id=對(duì)應(yīng)的一級(jí)權(quán)限)
如果用戶(hù)擁有某些權(quán)限就在用戶(hù)權(quán)限表中創(chuàng)建一條記錄
后端實(shí)現(xiàn)
后端實(shí)現(xiàn)起來(lái)非常的方便,我使用的方法是定義一個(gè)注解通過(guò)AOP掃描這個(gè)注解,然后判斷當(dāng)前用戶(hù)是否擁有對(duì)應(yīng)的權(quán)限,如果沒(méi)有直接拋出異常,通過(guò)全局異常處理器進(jìn)行捕捉
定義注解類(lèi):
因?yàn)楹笈_(tái)管理實(shí)現(xiàn)的非常簡(jiǎn)單,幾乎不存在多個(gè)表之間相互嵌套,因此我用了個(gè)value表示當(dāng)前Controller需要使用到的權(quán)限的ID
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface PermissionCheckAnnotation {
int value();
}
定義枚舉類(lèi):
主要用來(lái)定義對(duì)應(yīng)權(quán)限的ID值
public class PermissionEnum {
public final static int USER_QUERY = 14;
public final static int USER_UPDATE = 15;
public final static int USER_CREATE = 16;
}
定義AOP切面
@Pointcut("execution(掃描當(dāng)前包中的全部文件) && @annotation(annotation.PermissionCheckAnnotation)")
public void pt(){}
@Around("pt()")
public Object PermissionCheck(ProceedingJoinPoint jp) throws Throwable {
MethodSignature signature = (MethodSignature) jp.getSignature();
// 反射拿到權(quán)限ID
PermissionCheckAnnotation annotation = signature.getMethod().getAnnotation(PermissionCheckAnnotation.class);
int value = annotation.value();
// 獲取用戶(hù)ID
Integer userId = UserContext.getUserId();
// 查詢(xún)當(dāng)前用戶(hù)和權(quán)限ID之間是否存在關(guān)聯(lián)關(guān)系,如果不存在拋出異常
Integer hasPermission = userPermissionMapper.hasPermission(value, userId);
if (hasPermission == null || hasPermission == 0){
throw new PermissionException("權(quán)限不足,請(qǐng)聯(lián)系管理員");
}
return jp.proceed();
}
定義controller
@PermissionCheckAnnotation(PermissionEnum.USER_CREATE)
@PostMapping("/createUser")
public Result<String> createUser() {
}
后端修改權(quán)限
前端將修改完的權(quán)限發(fā)送過(guò)來(lái),大體格式就是一個(gè)整數(shù)數(shù)組([1,2,3,4,5]),表示當(dāng)前用戶(hù)的全部權(quán)限的ID集合
權(quán)限更新的主要思路就是將該用戶(hù)的全部權(quán)限刪除,再重建
如果嫌棄太慢的話(huà),我覺(jué)得可以取交集之類(lèi)的操作,提升效率,或者再額外定義一個(gè)字段,用來(lái)判斷當(dāng)前用戶(hù)權(quán)限的狀態(tài)(delete字段)這樣應(yīng)該會(huì)比delete insert效率高一些
不過(guò)俺是個(gè)菜鳥(niǎo)小白+懶狗,怎么簡(jiǎn)單怎么來(lái)了
刪除用戶(hù)不擁有的權(quán)限
<delete id="deletePermission">
delete from user_permission where user_id = #{userId}
and permission_id not in
<foreach item="item" collection="permissionList" open="(" close=")" separator=",">
#{item}
</foreach>
</delete>
插入新權(quán)限
因?yàn)槭侨坎迦?,?quán)限可能會(huì)產(chǎn)生重復(fù),因此我給user_id和permission_id添加唯一約束,并在插入時(shí)忽略錯(cuò)誤
<insert id="createPermission">
insert ignore into user_permission
<foreach collection="permissionList" open="values" item="item" separator=",">
(null,#{userId},#{item})
</foreach>
</insert>
前端
我前端不是很好,只會(huì)單純畫(huà)個(gè)界面,因此我還沒(méi)有實(shí)現(xiàn)按鈕級(jí)別的權(quán)限控制,不過(guò)大體思路是自定義指令,然后檢查是否擁有對(duì)應(yīng)的權(quán)限,如果沒(méi)有權(quán)限直接隱藏該按鈕
至于菜單級(jí)別的權(quán)限,我的做法是每次都發(fā)送一個(gè)請(qǐng)求,判斷能用多少菜單,即使被人扒出來(lái)其他界面,后端也做了權(quán)限的校驗(yàn),數(shù)據(jù)還是拿不到
這里主要記錄下如何在前端修改權(quán)限
查詢(xún)返回的數(shù)據(jù)格式大致如下
{
id: 15
level: 2
name: "操作查詢(xún)"
parentId: 1
remark: "操作菜單下的查詢(xún)功能"
status: 1
}
{
id: 1
level: 1
name: "操作菜單"
parentId: null
remark: "操作菜單"
status: 1
}
我想要在element-Plus中的樹(shù)形控件中實(shí)現(xiàn)展示,操作功能,大致需要將上面的數(shù)據(jù)變成這樣的格式
const data: Tree[] = [
{
label: 'Level one 1',
children: [
{
label: 'Level two 1-1',
},
],
},
]
這里通過(guò)dfs實(shí)現(xiàn)的(同層權(quán)限之間不會(huì)產(chǎn)生交集,所以應(yīng)該能用最小生成樹(shù)完成,不過(guò)俺是個(gè)懶狗,寫(xiě)了個(gè)最簡(jiǎn)單的方式)
const st = new Map();
for (let i = 0; i < res.length; i++) {
st.set(res[i].id, 0);
}
const list = [];
for (let i = 0; i < res.length; i++) {
if (res[i].parentId == null) {
const children = dfs(i, res);
list.push(children);
}
}
tree.value = list;
function dfs(idx, res) {
st.set(res[idx].id, 1);
const children = []
for (let i = 0; i < res.length; i++) {
if (st.get(res[i].id) == 1) {
continue;
}
if (res[i].parentId == res[idx].id) {
children.push(dfs(i, res))
}
}
if (children.length == 0)
return { id: res[idx].id, label: res[idx].name }
return { id: res[idx].id, label: res[idx].name, children }
}
然后把操作完的數(shù)據(jù)扔到elTree中
<el-tree v-loading="treeLoading"
@check="checkChange"
style="max-width: 200px"
ref="elTreeRef"
:data="tree"
:props="defaultProps"
show-checkbox
node-key="id" />
然后就是用戶(hù)的初始權(quán)限,通過(guò)點(diǎn)擊不同的用戶(hù)向后端查詢(xún)?cè)撚脩?hù)擁有的權(quán)限,el-tree有個(gè)屬性可以設(shè)置默認(rèn)勾選的復(fù)選框,但我不知道為什么點(diǎn)擊不同用戶(hù)時(shí),樹(shù)中上一個(gè)勾選的復(fù)選框不會(huì)被取消,因此使用了el-tree的方法,當(dāng)點(diǎn)擊不同用戶(hù)時(shí)觸發(fā),傳入的數(shù)據(jù)是一個(gè)整數(shù)數(shù)組([1,2,3]),表示勾選的節(jié)點(diǎn)的id,需要在el-tree標(biāo)簽中提前指定node-key
elTreeRef.value.setCheckedKeys(hasPermission.value)
最后就是權(quán)限修改,大致就是用戶(hù)點(diǎn)擊不同的復(fù)選框,選擇或取消不同的權(quán)限,通過(guò)綁定@check事件,然后獲取里面的數(shù)據(jù),這里說(shuō)一下當(dāng)點(diǎn)擊子復(fù)選框時(shí),父復(fù)選框也會(huì)觸發(fā)一次,當(dāng)父選框下的全部子復(fù)選框都取消時(shí),父復(fù)選框也會(huì)取消,通過(guò)下面這個(gè)方法能拿到當(dāng)前勾選的復(fù)選框,然后發(fā)送數(shù)據(jù)
const checkChange = function (data1, data2) {
currentPermission = [...data2.checkedKeys, ...data2.halfCheckedKeys]
}
總結(jié)
就這樣,實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的權(quán)限校驗(yàn)?zāi)P?,雖然缺少了角色表,但大體功能上大差不差,添加上角色表后,可能還得考慮權(quán)限的遷移,權(quán)限的分配等等問(wèn)題
不過(guò)對(duì)于一個(gè)簡(jiǎn)單的系統(tǒng)來(lái)說(shuō)還是十分夠用力
還有為什么csdn還對(duì)封面圖大小設(shè)置了,把我的卡茲米都?jí)撼墒裁礃恿??????
到此這篇關(guān)于SpringBoot實(shí)現(xiàn)RBAC權(quán)限校驗(yàn)?zāi)P偷氖纠奈恼戮徒榻B到這了,更多相關(guān)SpringBoot RBAC權(quán)限校驗(yàn) 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- SpringBoot快速設(shè)置攔截器并實(shí)現(xiàn)權(quán)限驗(yàn)證的方法
- SpringBoot+Spring Security+JWT實(shí)現(xiàn)RESTful Api權(quán)限控制的方法
- SpringBoot集成Shiro進(jìn)行權(quán)限控制和管理的示例
- SpringBoot2.0整合Shiro框架實(shí)現(xiàn)用戶(hù)權(quán)限管理的示例
- SpringBoot 監(jiān)控管理模塊actuator沒(méi)有權(quán)限的問(wèn)題解決方法
- Springboot 如何使用 SaToken 進(jìn)行登錄認(rèn)證、權(quán)限管理及路由規(guī)則接口攔截
- 詳解關(guān)于springboot-actuator監(jiān)控的401無(wú)權(quán)限訪問(wèn)
- SpringBoot + Shiro前后端分離權(quán)限
- 解決springboot+shiro 權(quán)限攔截失效的問(wèn)題
- springboot集成springsecurity 使用OAUTH2做權(quán)限管理的教程
- Springboot+mybatis-plus+注解實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離
相關(guān)文章
-
Java中的CyclicBarrier循環(huán)柵欄解析
這篇文章主要介紹了Java中的CyclicBarrier循環(huán)柵欄解析,從字面上的意思可以知道,這個(gè)類(lèi)的中文意思是"循環(huán)柵欄",大概的意思就是一個(gè)可循環(huán)利用的屏障,它的作用就是會(huì)讓所有線程都等待完成后才會(huì)繼續(xù)下一步行動(dòng),需要的朋友可以參考下 2023-12-12
-
解決程序啟動(dòng)報(bào)錯(cuò)org.springframework.context.ApplicationContextExcept
文章描述了一個(gè)Spring Boot項(xiàng)目在不同環(huán)境下啟動(dòng)時(shí)出現(xiàn)差異的問(wèn)題,通過(guò)分析報(bào)錯(cuò)信息,發(fā)現(xiàn)是由于導(dǎo)入`spring-boot-starter-tomcat`依賴(lài)時(shí)定義的scope導(dǎo)致的配置問(wèn)題,調(diào)整依賴(lài)導(dǎo)入配置后,解決了啟動(dòng)錯(cuò)誤 2024-11-11
-
springboot整合liteflow的實(shí)現(xiàn)示例
本文主要介紹了在Spring Boot項(xiàng)目中整合Liteflow規(guī)則引擎,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧 2024-12-12
-
Java基礎(chǔ)之教你如何正確運(yùn)用依賴(lài)注入
最近發(fā)現(xiàn)很多使用Spring框架的Java代碼存在依賴(lài)注入方式的誤用,甚至是濫用.因此整理了這篇文章,歡迎大家一起探討,需要的朋友可以參考下 2021-05-05
-
剖析Java中阻塞隊(duì)列的實(shí)現(xiàn)原理及應(yīng)用場(chǎng)景
這篇文章主要介紹了剖析Java中阻塞隊(duì)列的實(shí)現(xiàn)原理及應(yīng)用場(chǎng)景,這里也對(duì)阻塞和非阻塞隊(duì)列的不同之處進(jìn)行了對(duì)比,需要的朋友可以參考下 2015-12-12
-
Idea2019創(chuàng)建Springboot Web項(xiàng)目的方法步驟
這篇文章主要介紹了Idea2019創(chuàng)建Springboot Web項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧 2019-10-10
-
springMVC框架下JQuery傳遞并解析Json數(shù)據(jù)
json作為一種輕量級(jí)的數(shù)據(jù)交換格式,在前后臺(tái)數(shù)據(jù)交換中占據(jù)著非常重要的地位,這篇文章主要介紹了springMVC框架下JQuery傳遞并解析Json數(shù)據(jù),有興趣的可以了解一下。 2017-01-01
-
Java根據(jù)前端傳回的圖片生成pdf并且加密碼和水印
這篇文章主要為大家詳細(xì)介紹了java如何根據(jù)前端傳回的png圖片數(shù)組,后端加水印加密碼生成pdf并返回給前端,感興趣的小伙伴可以參考一下 2025-01-01
-
java開(kāi)發(fā)之SQL語(yǔ)句中DATE_FORMAT函數(shù)舉例詳解
要將日期值格式化為特定格式,請(qǐng)使用DATE_FORMAT函數(shù),下面這篇文章主要給大家介紹了關(guān)于java開(kāi)發(fā)之SQL語(yǔ)句中DATE_FORMAT函數(shù)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下 2024-05-05
最新評(píng)論
最近想做一個(gè)管理系統(tǒng),記錄下自己的消費(fèi)記錄,實(shí)現(xiàn)個(gè)文件上傳之類(lèi)的功能,正好最近看了下RBAC模型,想學(xué)習(xí)一下,在這分享下實(shí)現(xiàn)過(guò)程,方便以后查看
RBAC模型簡(jiǎn)單來(lái)說(shuō)就是創(chuàng)建5張表(用戶(hù)表,角色表,權(quán)限表,角色與用戶(hù)表,角色與權(quán)限表)
通過(guò)給用戶(hù)分配不同角色,以及給角色分配不同權(quán)限,實(shí)現(xiàn)用戶(hù)的權(quán)限控制
不過(guò)這次我做的項(xiàng)目是個(gè)后臺(tái)管理系統(tǒng),主要是自己和朋友使用,所以角色其實(shí)就分成了管理員和普通用戶(hù),因此我省略掉了角色和角色權(quán)限表,這樣雖然不夠靈活,但畢竟使用的人少,所以管理起來(lái)也非常方便
數(shù)據(jù)庫(kù)表
數(shù)據(jù)庫(kù)主要?jiǎng)?chuàng)建三張表
用戶(hù)表:
主要用來(lái)使用用戶(hù)登錄
- id 用戶(hù)主鍵
- account 登錄賬號(hào)
- password 登錄密碼
- type 區(qū)分普通角色和管理員身份
- username 用戶(hù)名
- status 用戶(hù)的狀態(tài)
+-----------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------+-------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | account | char(15) | YES | | NULL | | | password | varchar(50) | YES | | NULL | | | type | int | YES | | NULL | | | username | varchar(20) | YES | | NULL | | | status | int | YES | | NULL | | +-----------+-------------+------+-----+---------+----------------+
權(quán)限表:
主要用來(lái)記錄權(quán)限信息
- id 權(quán)限主鍵
- name 權(quán)限名稱(chēng)
- parent_id 父權(quán)限的id 如果沒(méi)有父權(quán)限則為null
- status 權(quán)限是否啟用
- remark 權(quán)限備注
- level 權(quán)限的層級(jí),主要用來(lái)排序的字段
+-------------+-------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-------------+-------------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | name | varchar(20) | YES | | NULL | | | parent_id | int | YES | | NULL | | | status | int | YES | | NULL | | | remark | varchar(50) | YES | | NULL | | | create_user | int | YES | | NULL | | | create_date | date | YES | | NULL | | | update_user | int | YES | | NULL | | | update_date | date | YES | | NULL | | | level | int | YES | | NULL | | +-------------+-------------+------+-----+---------+----------------+
用戶(hù)權(quán)限表:
實(shí)現(xiàn)多對(duì)多關(guān)系的表
- id 主鍵
- user_id 用戶(hù)的ID
- permission_id 權(quán)限的ID
+---------------+------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------------+------+------+-----+---------+----------------+ | id | int | NO | PRI | NULL | auto_increment | | user_id | int | YES | MUL | NULL | | | permission_id | int | YES | | NULL | | +---------------+------+------+-----+---------+----------------+
主要解釋下權(quán)限表,因?yàn)楣芾硐到y(tǒng)需要根據(jù)權(quán)限判斷是否提供菜單,因此我將菜單作為了一級(jí)權(quán)限(parent_id=null),一級(jí)權(quán)限下的增刪改查等操作定義為二級(jí)權(quán)限(parent_id=對(duì)應(yīng)的一級(jí)權(quán)限)
如果用戶(hù)擁有某些權(quán)限就在用戶(hù)權(quán)限表中創(chuàng)建一條記錄
后端實(shí)現(xiàn)
后端實(shí)現(xiàn)起來(lái)非常的方便,我使用的方法是定義一個(gè)注解通過(guò)AOP掃描這個(gè)注解,然后判斷當(dāng)前用戶(hù)是否擁有對(duì)應(yīng)的權(quán)限,如果沒(méi)有直接拋出異常,通過(guò)全局異常處理器進(jìn)行捕捉
定義注解類(lèi):
因?yàn)楹笈_(tái)管理實(shí)現(xiàn)的非常簡(jiǎn)單,幾乎不存在多個(gè)表之間相互嵌套,因此我用了個(gè)value表示當(dāng)前Controller需要使用到的權(quán)限的ID
@Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface PermissionCheckAnnotation { int value(); }
定義枚舉類(lèi):
主要用來(lái)定義對(duì)應(yīng)權(quán)限的ID值
public class PermissionEnum { public final static int USER_QUERY = 14; public final static int USER_UPDATE = 15; public final static int USER_CREATE = 16; }
定義AOP切面
@Pointcut("execution(掃描當(dāng)前包中的全部文件) && @annotation(annotation.PermissionCheckAnnotation)") public void pt(){} @Around("pt()") public Object PermissionCheck(ProceedingJoinPoint jp) throws Throwable { MethodSignature signature = (MethodSignature) jp.getSignature(); // 反射拿到權(quán)限ID PermissionCheckAnnotation annotation = signature.getMethod().getAnnotation(PermissionCheckAnnotation.class); int value = annotation.value(); // 獲取用戶(hù)ID Integer userId = UserContext.getUserId(); // 查詢(xún)當(dāng)前用戶(hù)和權(quán)限ID之間是否存在關(guān)聯(lián)關(guān)系,如果不存在拋出異常 Integer hasPermission = userPermissionMapper.hasPermission(value, userId); if (hasPermission == null || hasPermission == 0){ throw new PermissionException("權(quán)限不足,請(qǐng)聯(lián)系管理員"); } return jp.proceed(); }
定義controller
@PermissionCheckAnnotation(PermissionEnum.USER_CREATE) @PostMapping("/createUser") public Result<String> createUser() { }
后端修改權(quán)限
前端將修改完的權(quán)限發(fā)送過(guò)來(lái),大體格式就是一個(gè)整數(shù)數(shù)組([1,2,3,4,5]),表示當(dāng)前用戶(hù)的全部權(quán)限的ID集合
權(quán)限更新的主要思路就是將該用戶(hù)的全部權(quán)限刪除,再重建
如果嫌棄太慢的話(huà),我覺(jué)得可以取交集之類(lèi)的操作,提升效率,或者再額外定義一個(gè)字段,用來(lái)判斷當(dāng)前用戶(hù)權(quán)限的狀態(tài)(delete字段)這樣應(yīng)該會(huì)比delete insert效率高一些
不過(guò)俺是個(gè)菜鳥(niǎo)小白+懶狗,怎么簡(jiǎn)單怎么來(lái)了
刪除用戶(hù)不擁有的權(quán)限
<delete id="deletePermission"> delete from user_permission where user_id = #{userId} and permission_id not in <foreach item="item" collection="permissionList" open="(" close=")" separator=","> #{item} </foreach> </delete>
插入新權(quán)限
因?yàn)槭侨坎迦?,?quán)限可能會(huì)產(chǎn)生重復(fù),因此我給user_id和permission_id添加唯一約束,并在插入時(shí)忽略錯(cuò)誤
<insert id="createPermission"> insert ignore into user_permission <foreach collection="permissionList" open="values" item="item" separator=","> (null,#{userId},#{item}) </foreach> </insert>
前端
我前端不是很好,只會(huì)單純畫(huà)個(gè)界面,因此我還沒(méi)有實(shí)現(xiàn)按鈕級(jí)別的權(quán)限控制,不過(guò)大體思路是自定義指令,然后檢查是否擁有對(duì)應(yīng)的權(quán)限,如果沒(méi)有權(quán)限直接隱藏該按鈕
至于菜單級(jí)別的權(quán)限,我的做法是每次都發(fā)送一個(gè)請(qǐng)求,判斷能用多少菜單,即使被人扒出來(lái)其他界面,后端也做了權(quán)限的校驗(yàn),數(shù)據(jù)還是拿不到
這里主要記錄下如何在前端修改權(quán)限
查詢(xún)返回的數(shù)據(jù)格式大致如下
{ id: 15 level: 2 name: "操作查詢(xún)" parentId: 1 remark: "操作菜單下的查詢(xún)功能" status: 1 } { id: 1 level: 1 name: "操作菜單" parentId: null remark: "操作菜單" status: 1 }
我想要在element-Plus中的樹(shù)形控件中實(shí)現(xiàn)展示,操作功能,大致需要將上面的數(shù)據(jù)變成這樣的格式
const data: Tree[] = [ { label: 'Level one 1', children: [ { label: 'Level two 1-1', }, ], }, ]
這里通過(guò)dfs實(shí)現(xiàn)的(同層權(quán)限之間不會(huì)產(chǎn)生交集,所以應(yīng)該能用最小生成樹(shù)完成,不過(guò)俺是個(gè)懶狗,寫(xiě)了個(gè)最簡(jiǎn)單的方式)
const st = new Map(); for (let i = 0; i < res.length; i++) { st.set(res[i].id, 0); } const list = []; for (let i = 0; i < res.length; i++) { if (res[i].parentId == null) { const children = dfs(i, res); list.push(children); } } tree.value = list; function dfs(idx, res) { st.set(res[idx].id, 1); const children = [] for (let i = 0; i < res.length; i++) { if (st.get(res[i].id) == 1) { continue; } if (res[i].parentId == res[idx].id) { children.push(dfs(i, res)) } } if (children.length == 0) return { id: res[idx].id, label: res[idx].name } return { id: res[idx].id, label: res[idx].name, children } }
然后把操作完的數(shù)據(jù)扔到elTree中
<el-tree v-loading="treeLoading" @check="checkChange" style="max-width: 200px" ref="elTreeRef" :data="tree" :props="defaultProps" show-checkbox node-key="id" />
然后就是用戶(hù)的初始權(quán)限,通過(guò)點(diǎn)擊不同的用戶(hù)向后端查詢(xún)?cè)撚脩?hù)擁有的權(quán)限,el-tree有個(gè)屬性可以設(shè)置默認(rèn)勾選的復(fù)選框,但我不知道為什么點(diǎn)擊不同用戶(hù)時(shí),樹(shù)中上一個(gè)勾選的復(fù)選框不會(huì)被取消,因此使用了el-tree的方法,當(dāng)點(diǎn)擊不同用戶(hù)時(shí)觸發(fā),傳入的數(shù)據(jù)是一個(gè)整數(shù)數(shù)組([1,2,3]),表示勾選的節(jié)點(diǎn)的id,需要在el-tree標(biāo)簽中提前指定node-key
elTreeRef.value.setCheckedKeys(hasPermission.value)
最后就是權(quán)限修改,大致就是用戶(hù)點(diǎn)擊不同的復(fù)選框,選擇或取消不同的權(quán)限,通過(guò)綁定@check事件,然后獲取里面的數(shù)據(jù),這里說(shuō)一下當(dāng)點(diǎn)擊子復(fù)選框時(shí),父復(fù)選框也會(huì)觸發(fā)一次,當(dāng)父選框下的全部子復(fù)選框都取消時(shí),父復(fù)選框也會(huì)取消,通過(guò)下面這個(gè)方法能拿到當(dāng)前勾選的復(fù)選框,然后發(fā)送數(shù)據(jù)
const checkChange = function (data1, data2) { currentPermission = [...data2.checkedKeys, ...data2.halfCheckedKeys] }
總結(jié)
就這樣,實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的權(quán)限校驗(yàn)?zāi)P?,雖然缺少了角色表,但大體功能上大差不差,添加上角色表后,可能還得考慮權(quán)限的遷移,權(quán)限的分配等等問(wèn)題
不過(guò)對(duì)于一個(gè)簡(jiǎn)單的系統(tǒng)來(lái)說(shuō)還是十分夠用力
還有為什么csdn還對(duì)封面圖大小設(shè)置了,把我的卡茲米都?jí)撼墒裁礃恿??????
到此這篇關(guān)于SpringBoot實(shí)現(xiàn)RBAC權(quán)限校驗(yàn)?zāi)P偷氖纠奈恼戮徒榻B到這了,更多相關(guān)SpringBoot RBAC權(quán)限校驗(yàn) 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- SpringBoot快速設(shè)置攔截器并實(shí)現(xiàn)權(quán)限驗(yàn)證的方法
- SpringBoot+Spring Security+JWT實(shí)現(xiàn)RESTful Api權(quán)限控制的方法
- SpringBoot集成Shiro進(jìn)行權(quán)限控制和管理的示例
- SpringBoot2.0整合Shiro框架實(shí)現(xiàn)用戶(hù)權(quán)限管理的示例
- SpringBoot 監(jiān)控管理模塊actuator沒(méi)有權(quán)限的問(wèn)題解決方法
- Springboot 如何使用 SaToken 進(jìn)行登錄認(rèn)證、權(quán)限管理及路由規(guī)則接口攔截
- 詳解關(guān)于springboot-actuator監(jiān)控的401無(wú)權(quán)限訪問(wèn)
- SpringBoot + Shiro前后端分離權(quán)限
- 解決springboot+shiro 權(quán)限攔截失效的問(wèn)題
- springboot集成springsecurity 使用OAUTH2做權(quán)限管理的教程
- Springboot+mybatis-plus+注解實(shí)現(xiàn)數(shù)據(jù)權(quán)限隔離
相關(guān)文章
Java中的CyclicBarrier循環(huán)柵欄解析
這篇文章主要介紹了Java中的CyclicBarrier循環(huán)柵欄解析,從字面上的意思可以知道,這個(gè)類(lèi)的中文意思是"循環(huán)柵欄",大概的意思就是一個(gè)可循環(huán)利用的屏障,它的作用就是會(huì)讓所有線程都等待完成后才會(huì)繼續(xù)下一步行動(dòng),需要的朋友可以參考下2023-12-12解決程序啟動(dòng)報(bào)錯(cuò)org.springframework.context.ApplicationContextExcept
文章描述了一個(gè)Spring Boot項(xiàng)目在不同環(huán)境下啟動(dòng)時(shí)出現(xiàn)差異的問(wèn)題,通過(guò)分析報(bào)錯(cuò)信息,發(fā)現(xiàn)是由于導(dǎo)入`spring-boot-starter-tomcat`依賴(lài)時(shí)定義的scope導(dǎo)致的配置問(wèn)題,調(diào)整依賴(lài)導(dǎo)入配置后,解決了啟動(dòng)錯(cuò)誤2024-11-11springboot整合liteflow的實(shí)現(xiàn)示例
本文主要介紹了在Spring Boot項(xiàng)目中整合Liteflow規(guī)則引擎,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-12-12Java基礎(chǔ)之教你如何正確運(yùn)用依賴(lài)注入
最近發(fā)現(xiàn)很多使用Spring框架的Java代碼存在依賴(lài)注入方式的誤用,甚至是濫用.因此整理了這篇文章,歡迎大家一起探討,需要的朋友可以參考下2021-05-05剖析Java中阻塞隊(duì)列的實(shí)現(xiàn)原理及應(yīng)用場(chǎng)景
這篇文章主要介紹了剖析Java中阻塞隊(duì)列的實(shí)現(xiàn)原理及應(yīng)用場(chǎng)景,這里也對(duì)阻塞和非阻塞隊(duì)列的不同之處進(jìn)行了對(duì)比,需要的朋友可以參考下2015-12-12Idea2019創(chuàng)建Springboot Web項(xiàng)目的方法步驟
這篇文章主要介紹了Idea2019創(chuàng)建Springboot Web項(xiàng)目的方法步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10springMVC框架下JQuery傳遞并解析Json數(shù)據(jù)
json作為一種輕量級(jí)的數(shù)據(jù)交換格式,在前后臺(tái)數(shù)據(jù)交換中占據(jù)著非常重要的地位,這篇文章主要介紹了springMVC框架下JQuery傳遞并解析Json數(shù)據(jù),有興趣的可以了解一下。2017-01-01Java根據(jù)前端傳回的圖片生成pdf并且加密碼和水印
這篇文章主要為大家詳細(xì)介紹了java如何根據(jù)前端傳回的png圖片數(shù)組,后端加水印加密碼生成pdf并返回給前端,感興趣的小伙伴可以參考一下2025-01-01java開(kāi)發(fā)之SQL語(yǔ)句中DATE_FORMAT函數(shù)舉例詳解
要將日期值格式化為特定格式,請(qǐng)使用DATE_FORMAT函數(shù),下面這篇文章主要給大家介紹了關(guān)于java開(kāi)發(fā)之SQL語(yǔ)句中DATE_FORMAT函數(shù)的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-05-05