知識庫 / Spring / Spring Security RSS 訂閱

Spring Security 中授權與角色

Spring Security
HongKong
10
02:22 PM · Dec 06 ,2025

1. 概述

在本文中,我們將解釋 Spring Security 中 角色 (Role)授權 (GrantedAuthority) 之間的微妙但重要的區別。有關角色和授權的更詳細信息,請參閲此處。

2. GrantedAuthority

在 Spring Security 中,我們可以將每個 GrantedAuthority 視為一個獨立的權限。例如,可以包括 READ_AUTHORITYWRITE_PRIVILEGE,甚至 CAN_EXECUTE_AS_ROOT。重要的是要理解的是,名稱是任意的

當直接使用 GrantedAuthority,例如通過使用像 hasAuthority('READ_AUTHORITY') 這樣的表達式時,我們 以精細的方式限制訪問

正如你可能已經注意到,我們可以通過使用 authority 來引用 privilege 概念。

3. 擔任權威角色

類似於 Spring Security,我們可以將每個 角色 視為粗粒度的 GrantedAuthority,它以 String 形式表示,並以 “ROLE” 為前綴。 當直接使用 角色,例如通過表達式 hasRole(“ADMIN”),我們以粗粒度的方式限制訪問。

值得注意的是,默認的 “ROLE” 前綴是可以配置的,但如何進行配置超出了本文的範圍。

這兩個概念之間的核心區別在於我們如何使用該功能所賦予的語義。 對於框架而言,這種差異微乎其微——它基本上以完全相同的方式處理它們。

4. 作為容器的角色

現在我們已經瞭解了框架如何使用角色的概念,我們也將快速討論一種替代方案——即將角色用作權限/特權的容器

這是一種更高層次的角色使用方式——將角色變成面向業務的概念,而不是面向實現的。

Spring Security 框架沒有提供關於如何使用該概念的指導,因此選擇完全取決於實現細節。

5. Spring Security 配置

我們可以通過限制對 /protectedbyauthority 的訪問權限,僅限擁有 READ_AUTHORITY 的用户來演示細粒度的授權需求。

我們可以通過限制對 /protectedbyrole 的訪問權限,僅限擁有 ROLE_USER 的用户來演示粗粒度的授權需求。

讓我們在我們的安全配置中配置這樣一個場景:

@Override
protected void configure(HttpSecurity http) throws Exception {
    // ...
    .requestMatchers("/protectedbyrole").hasRole("USER")
    .requestMatchers("/protectedbyauthority").hasAuthority("READ_PRIVILEGE")
    // ...
}

6. 簡單數據初始化

現在我們對核心概念有了更深入的理解,接下來我們來探討在應用程序啓動時創建一些初始化數據。

這當然是一種非常簡單的方法,用於在開發過程中啓動時使用一些初步的測試用户——但這並不是在生產環境中處理數據的正確方式。

我們將監聽上下文刷新事件:

@Override
@Transactional
public void onApplicationEvent(ContextRefreshedEvent event) {
    MyPrivilege readPrivilege
      = createPrivilegeIfNotFound("READ_PRIVILEGE");
    MyPrivilege writePrivilege
      = createPrivilegeIfNotFound("WRITE_PRIVILEGE"); 
}

實際的實現在這裏並不重要——通常取決於你所使用的持久化解決方案。主要目的是——我們正在持久化代碼中使用的權威信息。

7. UserDetailsService

我們的 UserDetailsService 實現是權限映射發生的地方。當用户經過身份驗證後,我們的 getAuthorities() 方法會填充並返回一個 UserDetails 對象:

private Collection<? extends GrantedAuthority> getAuthorities(
  Collection<Role> roles) {
    List<GrantedAuthority> authorities = new ArrayList<>();
    for (Role role: roles) {
        authorities.add(new SimpleGrantedAuthority(role.getName()));
        authorities.addAll(role.getPrivileges()
                 .stream()
                 .map(p -> new SimpleGrantedAuthority(p.getName()))
                 .collect(Collectors.toList()));
    }
    
    return authorities;
}

8. 運行和測試示例

我們可以執行 RolesAuthoritiesApplication Java 應用程序,該應用程序位於 GitHub 項目

要查看基於角色的授權在行動中的效果,我們需要:

  • 訪問 http://localhost:8082/protectedbyrole
  • 使用用户名 [email&nbsp;protected](密碼為 “user”)進行身份驗證
  • 記錄成功的授權
  • 訪問 http://localhost:8082/protectedbyauthority
  • 記錄未成功的授權

要查看基於權限的授權在行動中的效果,我們需要註銷應用程序,然後:

  • 訪問 http://localhost:8082/protectedbyauthority
  • 使用用户名 [email&nbsp;protected] / admin 進行身份驗證
  • 記錄成功的授權
  • 訪問 http://localhsot:8082/protectedbyrole
  • 記錄未成功的授權

9. 結論

在本快速教程中,我們探討了 Spring Security 中 RoleGrantedAuthority 之間的微妙但重要的區別。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.