👉 這是一個或許對你有用的社群
《專案實戰(影片)》:從書中學,往事上“練” 《網際網路高頻面試題》:面朝簡歷學習,春暖花開 《架構 x 系統設計》:摧枯拉朽,掌控面試高頻場景題 《精進 Java 學習指南》:系統學習,網際網路主流技術棧 《必讀 Java 原始碼專欄》:知其然,知其所以然

👉這是一個或許對你有用的開源專案國產 Star 破 10w+ 的開源專案,前端包括管理後臺 + 微信小程式,後端支援單體和微服務架構。功能涵蓋 RBAC 許可權、SaaS 多租戶、資料許可權、商城、支付、工作流、大屏報表、微信公眾號、ERP、CRM、AI 大模型等等功能:
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 雙版本

引言
基於 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 |
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. 許可權控制的註解設計
@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() {
// 方法邏輯
}
}
READ_DATA
許可權,updateConfig
方法需要使用者擁有 ADMIN
或 MANAGER
角色,而 makeRequest
方法需要檢查 REQUEST_LIMIT
型別的數量限制。許可權註解的實現細節
5. 切面實現
介紹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. 許可權控制的業務邏輯實現
UserService
、RoleService
和 PermissionService
。使用者許可權服務(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"是特殊角色
}
}
業務邏輯實現說明
@Autowired
註解來自動注入所需的資料訪問物件(如UserRepository
和 RoleRepository
)。這些服務提供了與資料庫互動的方法,以及基於這些資料執行許可權檢查的邏輯。UserService
和 RoleService
提供了獲取使用者和角色相關資訊的方法,而PermissionService
則使用這些資訊來執行實際的許可權檢查。這些服務可以被AOP切面或其他業務邏輯元件呼叫,以確保在執行敏感操作之前進行適當的許可權驗證。請注意,這些服務的實現可能需要根據具體的業務需求和資料庫設計進行調整。在實際應用中,還可能需要考慮效能最佳化、快取策略和安全性等因素。
7. 結論
總結
-
許可權控制的基本概念: 我們定義了組織許可權、個人許可權,並討論了許可權的層次結構和作用域,以及許可權與角色的關係。 -
系統需求分析: 我們描述了複雜的許可權控制需求,包括組織許可權、個人許可權、數量限制和特殊角色許可權,並確定了業務規則。 -
庫表設計: 我們設計了資料庫表結構,包括組織表、使用者表、角色表、許可權表以及相關的關聯表。 -
許可權控制的註解設計: 我們定義了三個註解:@PermissionRequired、@RoleRequired 和 @LimitRequired,用於標記需要許可權檢查的方法。 -
切面實現: 我們介紹了Spring AOP的基本概念,並實現了一個許可權檢查切面,包括組織許可權檢查、個人許可權檢查、數量限制檢查和特殊角色檢查。 -
許可權控制的業務邏輯實現: 我們實現了使用者許可權服務、角色許可權服務和許可權檢查服務,這些服務提供了與資料庫互動和執行許可權檢查的邏輯。
實現的優缺點
-
靈活性: 使用註解和AOP,我們可以靈活地在不同的方法上應用許可權控制,而不需要修改業務邏輯程式碼。 -
可維護性: 將許可權控制邏輯從業務邏輯中分離出來,使得程式碼更容易維護和擴充套件。 -
重用性: 定義的註解和切面可以在多個專案中重用,減少了重複程式碼。 -
安全性: 透過細緻的許可權控制,可以確保系統的安全性,防止未授權訪問。
-
複雜性: 實現一個複雜的許可權控制系統可能會增加系統的複雜性,特別是在設計和維護資料庫結構和業務邏輯時。 -
效能考慮: 許可權檢查可能會引入額外的效能開銷,特別是在涉及大量資料庫查詢的情況下。 -
安全性依賴: 系統的安全性高度依賴於許可權控制的實現,任何實現上的漏洞都可能導致安全風險。
未來可能的改進方向
-
快取策略: 為了提高效能,可以引入快取策略,減少對資料庫的直接查詢。 -
動態許可權更新: 支援動態更新許可權設定,而不需要重新部署或重啟應用程式。 -
細粒度許可權控制: 實現更細粒度的許可權控制,例如基於屬性的訪問控制(ABAC)。 -
審計和監控: 增加審計和監控功能,記錄所有許可權檢查的操作,以便進行安全分析和問題排查。 -
使用者介面: 開發一個使用者友好的管理介面,使管理員能夠輕鬆地管理使用者、角色和許可權。 -
多因素認證: 結合多因素認證(MFA)增強系統的安全性。





