老闆愛瞎改許可權怎麼辦:註解+AOP打造複雜許可權體系

👉 這是一個或許對你有用的社群
🐱 一對一交流/面試小冊/簡歷最佳化/求職解惑,歡迎加入芋道快速開發平臺知識星球。下面是星球提供的部分資料:
👉這是一個或許對你有用的開源專案
國產 Star 破 10w+ 的開源專案,前端包括管理後臺 + 微信小程式,後端支援單體和微服務架構。
功能涵蓋 RBAC 許可權、SaaS 多租戶、資料許可權、商城、支付、工作流、大屏報表、微信公眾號、ERPCRMAI 大模型等等功能:
  • Boot 多模組架構:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 微服務架構:https://gitee.com/zhijiantianya/yudao-cloud
  • 影片教程:https://doc.iocoder.cn
【國內首批】支援 JDK 17/21 + SpringBoot 3.3、JDK 8/11 + Spring Boot 2.7 雙版本 

引言

在軟體開發的世界裡,許可權控制是確保資料安全和業務流程合規性的關鍵。然而,當老闆或管理層頻繁地調整許可權設定時,這不僅會打亂開發節奏,還可能導致安全漏洞和效能問題。這種情況下,一個靈活、可擴充套件且易於管理的許可權控制系統就顯得尤為重要。
本文將探討如何使用Java註解和Spring AOP(面向切面程式設計)來構建一個複雜而強大的許可權控制體系。這個體系將能夠應對頻繁變更的許可權需求,同時確保系統的安全性和穩定性。
在這個體系中,我們將透過註解來宣告許可權需求,利用AOP來實現許可權檢查的邏輯。這種方法不僅可以減少程式碼侵入性,還能提高系統的可維護性和可擴充套件性。我們將從許可權控制的基本概念出發,逐步深入到系統需求分析、資料庫設計、註解定義、切面實現,以及業務邏輯的實現。
基於 Spring Boot + MyBatis Plus + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
  • 專案地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 影片教程:https://doc.iocoder.cn/video/

1. 許可權控制的基本概念

許可權控制是軟體系統安全性的核心組成部分,它確保了只有授權的使用者才能訪問特定的資源或執行特定的操作。在企業級應用中,許可權控制的複雜性隨著業務需求的增加而增加,這要求系統能夠靈活地處理不同層次和型別的許可權。

定義組織許可權和個人許可權

組織許可權通常指的是基於使用者所屬組織結構的許可權。這種許可權控制方式允許系統根據使用者所在的部門、團隊或公司層級來限制或授權訪問。例如,一個公司的財務部門可能只能訪問與財務相關的資料和功能,而不能訪問人力資源或研發部門的資料。
個人許可權則是指分配給特定使用者的許可權,與使用者所屬的組織結構無關。這種許可權控制方式允許系統為每個使用者定製訪問控制,以滿足個性化的需求。例如,一個銷售代表可能被授權訪問客戶資料,但僅限於他們自己的客戶記錄。

許可權的層次結構和作用域

許可權控制系統通常採用層次結構來組織許可權,以便於管理和維護。在這種結構中,許可權可以被分為不同的級別,每個級別對應不同的訪問控制需求。例如,一個簡單的許可權層次結構可能包括“只讀”、“編輯”和“管理”三個級別。
許可權的作用域決定了許可權的適用範圍。在某些系統中,許可權可能僅適用於特定的資源或操作,而在其他系統中,許可權可能跨越多個資源或操作。例如,一個使用者可能被授權訪問特定的資料庫表,但僅限於查詢操作,而不能進行資料的插入或刪除。

許可權與角色的關係

在許可權控制系統中,角色是將許可權分配給使用者的一個有效方式。透過為不同的角色分配不同的許可權集合,系統可以簡化許可權管理,並提高靈活性。例如,一個“管理員”角色可能擁有訪問和修改所有資源的許可權,而一個“普通使用者”角色可能只有訪問特定資源的許可權。
角色和許可權之間的關係通常是多對多的。一個使用者可以擁有多個角色,而一個角色也可以包含多個許可權。這種關係允許系統靈活地為使用者分配許可權,同時也方便了許可權的更新和維護。
在複雜的系統中,角色和許可權的關係可能更加複雜。例如,可能存在繼承關係,其中某些角色繼承了其他角色的許可權,或者存在特定的規則來限制角色的許可權組合。
基於 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
  • 專案地址:https://github.com/YunaiV/yudao-cloud
  • 影片教程:https://doc.iocoder.cn/video/

2. 系統需求分析

在設計一個複雜的許可權控制系統時,需求分析是至關重要的第一步。它確保我們能夠準確理解業務需求,並設計出一個既能滿足當前需求又能適應未來變化的系統。以下是對複雜許可權控制需求的描述,以及確定的業務規則。

描述複雜的許可權控制需求

組織許可權
組織許可權要求系統能夠根據使用者所屬的組織結構來授權或限制對特定功能的訪問。例如,一個組織可能有不同的部門,每個部門可能有不同的許可權集。
個人許可權
個人許可權要求系統能夠為每個使用者設定特定的許可權,這些許可權可能與使用者的角色或組織結構無關。例如,某些使用者可能被賦予訪問敏感資料的許可權。
數量限制
數量限制要求系統能夠跟蹤和限制使用者或組織可以執行的特定操作的數量。例如,一個使用者可能在一個時間段內只能提交一定數量的請求。
特殊角色許可權
特殊角色許可權要求系統能夠識別並授權某些特殊角色,這些角色可能擁有超越常規許可權控制的許可權。例如,系統管理員可能可以訪問系統的所有部分,不受常規許可權限制。

確定許可權控制的業務規則

  • 許可權繼承: 使用者繼承其所屬組織和角色的許可權。
  • 許可權覆蓋: 個人許可權可以覆蓋組織許可權。
  • 數量限制: 使用者的許可權可能受到數量限制,一旦達到限制,即使有許可權也無法執行操作。
  • 角色優先順序: 特殊角色可能具有高優先順序,可以覆蓋其他所有許可權設定。
  • 許可權審計: 所有許可權的授予和使用都應該被記錄和審計,以確保系統的安全性和合規性。

流程圖

下面是一個簡化的流程圖,展示瞭如何透過註解和切面來實現上述複雜的許可權控制需求:
在這個架構中,使用者請求首先到達Spring Security Filter,然後進入許可權檢查環節。許可權檢查包括特殊角色許可權檢查、數量限制檢查、組織許可權檢查和個人許可權檢查。如果使用者透過所有檢查,則可以訪問業務邏輯處理;如果任何一個檢查失敗,請求將被拒絕。

3. 庫表設計

在設計一個複雜的許可權控制系統時,資料庫的設計是核心部分,它需要能夠支援組織許可權、個人許可權、數量限制以及特殊角色許可權等功能。以下是針對這些需求設計的資料庫表結構。
組織表(Organizations
欄位名 資料型別 描述
organization_id INT 主鍵,自增
name VARCHAR 組織名稱
parent_id INT 父組織ID,用於層級關係
description TEXT 組織描述
使用者表(Users
欄位名 資料型別 描述
user_id INT 主鍵,自增
username VARCHAR 使用者名稱
password_hash VARCHAR 加密密碼
organization_id INT 所屬組織ID
email VARCHAR 電子郵件
created_at DATETIME 建立時間
updated_at DATETIME 更新時間
角色表(Roles
欄位名 資料型別 描述
role_id INT 主鍵,自增
name VARCHAR 角色名稱
description TEXT 角色描述
許可權表(Permissions
欄位名 資料型別 描述
permission_id INT 主鍵,自增
name VARCHAR 許可權名稱
description TEXT 許可權描述
角色許可權關聯表(Role_Permissions
欄位名 資料型別 描述
role_id INT 角色ID,外部索引鍵
permission_id INT 許可權ID,外部索引鍵
使用者角色關聯表(User_Roles
欄位名 資料型別 描述
user_id INT 使用者ID,外部索引鍵
role_id INT 角色ID,外部索引鍵
組織許可權關聯表(Organization_Permissions
欄位名 資料型別 描述
organization_id INT 組織ID,外部索引鍵
permission_id INT 許可權ID,外部索引鍵
limit INT 允許的運算元量限制
資料庫設計說明
  • 組織表: 儲存組織的基本資訊,包括層級關係。
  • 使用者表: 儲存使用者的基本資訊,包括所屬組織的ID。
  • 角色表: 儲存角色的基本資訊。
  • 許可權表: 儲存許可權的基本資訊。
  • 角色許可權關聯表: 定義角色和許可權之間的關係,一個角色可以有多個許可權,一個許可權可以被多個角色擁有。
  • 使用者角色關聯表: 定義使用者和角色之間的關係,一個使用者可以有多個角色。
  • 組織許可權關聯表: 定義組織和許可權之間的關係,並設定運算元量限制。
這種設計允許系統靈活地管理複雜的許可權控制需求,包括組織許可權、個人許可權、數量限制和特殊角色許可權。透過外部索引鍵關聯,可以確保資料的一致性和完整性。在實際應用中,可能還需要根據具體需求新增更多的欄位或表,例如,用於跟蹤許可權使用情況的審計日誌表。
請注意,這只是一個基本的設計,實際的資料庫設計可能需要根據具體的業務需求和效能要求進行調整。在實現時,還需要考慮索引最佳化、資料一致性、備份和恢復策略等因素。

4. 許可權控制的註解設計

在Java中,註解(Annotation)是一種特殊的介面,用於為程式碼提供元資料。在許可權控制中,註解可以被用來標記需要進行許可權檢查的方法或類。以下是為許可權控制設計的三個註解:@PermissionRequired@RoleRequired@LimitRequired
定義許可權註解(@PermissionRequired)
@PermissionRequired 註解用於標記需要特定許可權才能訪問的方法。它接受一個或多個許可權名稱作為引數,表示使用者必須擁有這些許可權之一才能執行該方法。
import

 java.lang.annotation.ElementType;

import

 java.lang.annotation.Retention;

import

 java.lang.annotation.RetentionPolicy;

import

 java.lang.annotation.Target;

@Target

({ElementType.METHOD, ElementType.TYPE})

@Retention

(RetentionPolicy.RUNTIME)

public@interface

 PermissionRequired {

    String[] value();

}

定義角色註解(@RoleRequired)
@RoleRequired 註解用於標記需要特定角色才能訪問的方法。它接受一個或多個角色名稱作為引數,表示使用者必須擁有這些角色之一才能執行該方法。
import

 java.lang.annotation.ElementType;

import

 java.lang.annotation.Retention;

import

 java.lang.annotation.RetentionPolicy;

import

 java.lang.annotation.Target;

@Target

({ElementType.METHOD, ElementType.TYPE})

@Retention

(RetentionPolicy.RUNTIME)

public@interface

 RoleRequired {

    String[] value();

}

定義數量限制註解(@LimitRequired)
@LimitRequired 註解用於標記需要檢查數量限制的方法。它接受一個引數,表示該方法對應的操作型別,這個操作型別將用於檢查使用者或組織是否達到了運算元量的限制。
import

 java.lang.annotation.ElementType;

import

 java.lang.annotation.Retention;

import

 java.lang.annotation.RetentionPolicy;

import

 java.lang.annotation.Target;

@Target

({ElementType.METHOD, ElementType.TYPE})

@Retention

(RetentionPolicy.RUNTIME)

public@interface

 LimitRequired {

String value()

;

}

使用示例
以下是如何使用這些註解的示例:
@RestController
@RequestMapping

(

"/api"

)

publicclassApiController

{

@PermissionRequired

(

"READ_DATA"

)

@GetMapping

(

"/data"

)

public

 ResponseEntity<?> getData() {

// 方法邏輯

    }

@RoleRequired

({

"ADMIN"

"MANAGER"

})

@PostMapping

(

"/config"

)

public

 ResponseEntity<?> updateConfig() {

// 方法邏輯

    }

@LimitRequired

(

"REQUEST_LIMIT"

)

@GetMapping

(

"/request"

)

public

 ResponseEntity<?> makeRequest() {

// 方法邏輯

    }

}

在這個示例中,getData 方法需要使用者擁有 READ_DATA 許可權,updateConfig 方法需要使用者擁有 ADMINMANAGER 角色,而 makeRequest 方法需要檢查 REQUEST_LIMIT 型別的數量限制。
許可權註解的實現細節
這些註解的實現將依賴於Spring框架的AOP(面向切面程式設計)功能。透過建立相應的切面,我們可以在方法執行前攔截這些註解,並執行許可權檢查邏輯。如果使用者沒有透過檢查,系統將阻止方法的執行並返回相應的錯誤資訊。

5. 切面實現

在Spring框架中,AOP(面向切面程式設計)是一種程式設計正規化,它允許我們在不修改業務邏輯程式碼的情況下,對橫切關注點(如日誌記錄、事務管理、許可權檢查等)進行模組化。透過使用AOP,我們可以將許可權檢查邏輯從業務邏輯中分離出來,提高程式碼的可維護性和重用性。
介紹Spring AOP的基本概念
Spring AOP基於代理機制,它允許我們在不改變現有程式碼結構的情況下,透過宣告額外的邏輯來擴充套件程式的行為。在Spring AOP中,主要涉及以下幾個核心概念:
  • 切面(Aspect): 切面是封裝橫切關注點的類,比如日誌、事務、許可權控制等。
  • 連線點(Join point): 連線點是程式執行過程中的一個點,如方法的呼叫或異常的丟擲。在Spring AOP中,連線點總是方法的執行。
  • 通知(Advice): 通知是切面在某連線點上的執行動作,它定義了在何時何地執行哪些邏輯。常見的通知型別包括:前置通知(Before)、後置通知(After)、返回通知(AfterReturning)、異常通知(AfterThrowing)和環繞通知(Around)。
  • 切點(Pointcut): 切點是一組匹配連線點的規則,它定義了哪些連線點會被切面所攔截。
  • 目標物件(Target Object): 目標物件是指被代理的物件,即包含連線點的物件。
  • 代理(Proxy): 代理是AOP框架建立的,它包裹了目標物件,並在執行連線點之前或之後執行通知。
定義許可權檢查切面(PermissionAspect)
PermissionAspect 是一個切面類,它使用Spring AOP來攔截被許可權註解標記的方法,並執行許可權檢查邏輯。
import

 org.aspectj.lang.annotation.Aspect;

import

 org.aspectj.lang.annotation.Pointcut;

import

 org.aspectj.lang.annotation.Before;

import

 org.springframework.stereotype.Component;

@Aspect
@Component
publicclassPermissionAspect

{

@Pointcut

(

"@annotation(permissionRequired)"

)

publicvoidpermissionPointcut(PermissionRequired permissionRequired)

{}

@Before

(

"permissionPointcut(permissionRequired)"

)

publicvoidcheckPermission(JoinPoint joinPoint, PermissionRequired permissionRequired)

{

// 獲取當前使用者

        User currentUser = SecurityContextHolder.getContext().getAuthentication().getPrincipal();

// 檢查使用者是否擁有所需的許可權
for

 (String permission : permissionRequired.value()) {

if

 (!permissionService.hasPermission(currentUser, permission)) {

thrownew

 AccessDeniedException(

"Access Denied: No permission to perform this operation."

);

            }

        }

    }

// 其他方法,如角色檢查、數量限制檢查等

}

組織許可權檢查
組織許可權檢查需要查詢資料庫,確定當前使用者所屬的組織是否擁有特定的許可權。
publicbooleanhasOrganizationPermission(User currentUser, String permission)

{

// 查詢資料庫,檢查使用者所屬組織是否有許可權

}

個人許可權檢查
個人許可權檢查需要查詢資料庫,確定當前使用者是否擁有特定的許可權。
publicbooleanhasUserPermission(User currentUser, String permission)

{

// 查詢資料庫,檢查使用者是否有許可權

}

數量限制檢查
數量限制檢查需要查詢資料庫,確定當前使用者或組織是否達到了運算元量的限制。
publicbooleanisLimitExceeded(User currentUser, String limitType)

{

// 查詢資料庫,檢查是否達到數量限制

}

特殊角色檢查
特殊角色檢查需要查詢資料庫,確定當前使用者是否擁有特殊角色。
publicbooleanhasSpecialRole(User currentUser)

{

// 查詢資料庫,檢查使用者是否擁有特殊角色

}

綜合檢查邏輯
在實際的許可權檢查邏輯中,我們需要綜合考慮組織許可權、個人許可權、數量限制和特殊角色。這可能涉及到多個方法的呼叫和複雜的邏輯判斷。
PermissionAspect中,我們可以使用環繞通知(Around Advice)來實現這一邏輯,確保在方法執行前後進行必要的檢查。

6. 許可權控制的業務邏輯實現

在許可權控制系統中,業務邏輯層是實現許可權檢查功能的核心。它負責與資料庫互動,獲取使用者、角色和許可權資料,並根據這些資料執行許可權檢查。以下是三個關鍵服務的實現:UserServiceRoleServicePermissionService
使用者許可權服務(UserService)
UserService 提供了與使用者相關的業務邏輯,包括獲取使用者資訊、使用者許可權以及使用者所屬的角色。
@Service
publicclassUserService

{

@Autowired
private

 UserRepository userRepository;

public User getUserById(Long userId)

{

return

 userRepository.findById(userId).orElse(

null

);

    }

public Set<String> getUserPermissions(Long userId)

{

        User user = getUserById(userId);

if

 (user != 

null

) {

            Set<Role> roles = user.getRoles();

            Set<String> permissions = 

new

 HashSet<>();

for

 (Role role : roles) {

                permissions.addAll(role.getPermissions());

            }

return

 permissions;

        }

return

 Collections.emptySet();

    }

// 其他使用者相關業務邏輯

}

角色許可權服務(RoleService)
RoleService 提供了與角色相關的業務邏輯,包括獲取角色資訊、角色許可權以及分配給角色的許可權。
@Service
publicclassRoleService

{

@Autowired
private

 RoleRepository roleRepository;

public Role getRoleById(Long roleId)

{

return

 roleRepository.findById(roleId).orElse(

null

);

    }

public Set<String> getRolePermissions(Long roleId)

{

        Role role = getRoleById(roleId);

if

 (role != 

null

) {

return

 role.getPermissions();

        }

return

 Collections.emptySet();

    }

// 其他角色相關業務邏輯

}

許可權檢查服務(PermissionService)
PermissionService 是許可權控制系統的核心,它負責檢查使用者是否擁有特定的許可權、角色以及是否超出運算元量限制。
@Service
publicclassPermissionService

{

@Autowired
private

 UserService userService;

@Autowired
private

 RoleService roleService;

publicbooleanhasPermission(User user, String permission)

{

if

 (user == 

null

) {

returnfalse

;

        }

        Set<String> userPermissions = userService.getUserPermissions(user.getId());

return

 userPermissions.contains(permission);

    }

publicbooleanhasRole(User user, String role)

{

if

 (user == 

null

) {

returnfalse

;

        }

        Set<Role> userRoles = user.getRoles();

for

 (Role userRole : userRoles) {

if

 (userRole.getName().equals(role)) {

returntrue

;

            }

        }

returnfalse

;

    }

publicbooleanisLimitExceeded(User user, String limitType)

{

// 實現檢查使用者或組織是否超出了運算元量限制
// 這可能涉及查詢資料庫中的計數器或使用快取
returnfalse

;

    }

// 特殊角色檢查
publicbooleanhasSpecialRole(User user)

{

// 實現檢查使用者是否擁有特殊角色
return

 hasRole(user, 

"ADMIN"

); 

// 示例:假設"ADMIN"是特殊角色

    }

}

業務邏輯實現說明
在這些服務中,我們使用了Spring框架的@Service註解來標記服務類,並使用@Autowired註解來自動注入所需的資料訪問物件(如UserRepositoryRoleRepository)。這些服務提供了與資料庫互動的方法,以及基於這些資料執行許可權檢查的邏輯。
UserServiceRoleService 提供了獲取使用者和角色相關資訊的方法,而PermissionService 則使用這些資訊來執行實際的許可權檢查。這些服務可以被AOP切面或其他業務邏輯元件呼叫,以確保在執行敏感操作之前進行適當的許可權驗證。
請注意,這些服務的實現可能需要根據具體的業務需求和資料庫設計進行調整。在實際應用中,還可能需要考慮效能最佳化、快取策略和安全性等因素。

7. 結論

在本文中,我們深入探討了如何使用Java註解和Spring AOP來實現一個複雜而靈活的許可權控制系統。我們從許可權控制的基本概念出發,分析了系統需求,並設計了相應的資料庫結構。
接著,我們定義了許可權註解,並實現了一個切面來攔截和檢查這些註解。最後,我們實現了業務邏輯層,提供了使用者許可權服務、角色許可權服務和許可權檢查服務。
總結
  • 許可權控制的基本概念: 我們定義了組織許可權、個人許可權,並討論了許可權的層次結構和作用域,以及許可權與角色的關係。
  • 系統需求分析: 我們描述了複雜的許可權控制需求,包括組織許可權、個人許可權、數量限制和特殊角色許可權,並確定了業務規則。
  • 庫表設計: 我們設計了資料庫表結構,包括組織表、使用者表、角色表、許可權表以及相關的關聯表。
  • 許可權控制的註解設計: 我們定義了三個註解:@PermissionRequired、@RoleRequired 和 @LimitRequired,用於標記需要許可權檢查的方法。
  • 切面實現: 我們介紹了Spring AOP的基本概念,並實現了一個許可權檢查切面,包括組織許可權檢查、個人許可權檢查、數量限制檢查和特殊角色檢查。
  • 許可權控制的業務邏輯實現: 我們實現了使用者許可權服務、角色許可權服務和許可權檢查服務,這些服務提供了與資料庫互動和執行許可權檢查的邏輯。
實現的優缺點
優點:
  • 靈活性: 使用註解和AOP,我們可以靈活地在不同的方法上應用許可權控制,而不需要修改業務邏輯程式碼。
  • 可維護性: 將許可權控制邏輯從業務邏輯中分離出來,使得程式碼更容易維護和擴充套件。
  • 重用性: 定義的註解和切面可以在多個專案中重用,減少了重複程式碼。
  • 安全性: 透過細緻的許可權控制,可以確保系統的安全性,防止未授權訪問。
缺點:
  • 複雜性: 實現一個複雜的許可權控制系統可能會增加系統的複雜性,特別是在設計和維護資料庫結構和業務邏輯時。
  • 效能考慮: 許可權檢查可能會引入額外的效能開銷,特別是在涉及大量資料庫查詢的情況下。
  • 安全性依賴: 系統的安全性高度依賴於許可權控制的實現,任何實現上的漏洞都可能導致安全風險。
未來可能的改進方向
  • 快取策略: 為了提高效能,可以引入快取策略,減少對資料庫的直接查詢。
  • 動態許可權更新: 支援動態更新許可權設定,而不需要重新部署或重啟應用程式。
  • 細粒度許可權控制: 實現更細粒度的許可權控制,例如基於屬性的訪問控制(ABAC)。
  • 審計和監控: 增加審計和監控功能,記錄所有許可權檢查的操作,以便進行安全分析和問題排查。
  • 使用者介面: 開發一個使用者友好的管理介面,使管理員能夠輕鬆地管理使用者、角色和許可權。
  • 多因素認證: 結合多因素認證(MFA)增強系統的安全性。
透過這些改進,我們可以進一步提高許可權控制系統的效能、安全性和使用者體驗。隨著技術的發展和業務需求的變化,許可權控制系統也需要不斷地演進和最佳化。

歡迎加入我的知識星球,全面提升技術能力。
👉 加入方式,長按”或“掃描”下方二維碼噢
星球的內容包括:專案實戰、面試招聘、原始碼解析、學習路線。
文章有幫助的話,在看,轉發吧。
謝謝支援喲 (*^__^*)

相關文章