知識庫 / Spring / Spring Security RSS 訂閱

Spring Security – 基於角色權限認證(Run-As)

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

1. 概述

在本教程中,我們將演示如何在 Spring Security 中使用 Run-As 身份驗證,並使用一個簡單的場景。

Run-As 的高層次解釋如下:用户可以以具有不同特權的另一個主體執行某些邏輯。

2. RunAsManager

為了增強服務層的安全性,我們首先將創建一個 MethodSecurityConfig 類,該類將負責提供臨時帶有額外特權 Authentication 對象。為此,首先,我們將使用 @Configuration@EnableMethodSecurity 註解對該類進行標註。然後,我們在其中創建一個 RunAsManager Bean:

@Configuration
@EnableMethodSecurity(securedEnabled = true)
public class MethodSecurityConfig{
    @Bean
    protected RunAsManager runAsManager() {
        RunAsManagerImpl runAsManager = new RunAsManagerImpl();
        runAsManager.setKey("MyRunAsKey");
        return runAsManager;
    }
}

這將注入我們的 runAsManager 到 spring 上下文中,替換默認實現,該實現返回一個 null

請注意 key 屬性——框架使用它來安全/驗證臨時 Authentication 對象(通過此管理器創建的)。

最後——生成的 Authentication 對象是一個 RunAsUserToken

注意:Authentication 現在與 authorization 在 Spring Security 中分離。 RunAsManager 僅用於現在已棄用的組件。 但 Spring Security 中尚不存在等效的替代方案。

3. 安全配置

為了驗證我們的臨時 Authentication 對象,我們將設置一個 RunAsImplAuthenticationProvider

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
    ...
    auth.authenticationProvider(runAsAuthenticationProvider());
}

@Bean
public AuthenticationProvider runAsAuthenticationProvider() {
    RunAsImplAuthenticationProvider authProvider = new RunAsImplAuthenticationProvider();
    authProvider.setKey("MyRunAsKey");
    return authProvider;
}

我們當然是以我們在管理器中使用的相同的密鑰來設置此項的,以便提供者可以驗證 RunAsUserToken 身份驗證對象是否使用相同的密鑰創建。

4. 使用帶有 @Secured 標記的控制器

現在,讓我們看看如何使用 Run-As 身份驗證替換:

@RestController
@RequestMapping("/runas")
class RunAsController {

    @Secured({ "ROLE_USER", "RUN_AS_REPORTER" })
    @RequestMapping
    public String tryRunAs() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        return "Current User Authorities inside this RunAS method only " + 
          auth.getAuthorities().toString();
    }

}

這裏最關鍵的是新的角色——RUN_AS_REPORTER。這是 Run-As 功能的觸發器,因為框架由於前綴的不同而與之處理方式不同。

當請求通過此邏輯執行時,我們會得到:

  • 在調用 .tryRunAs() 方法之前,當前用户權限是 [ROLE_USER]
  • 在 .tryRunAs() 方法內部,當前用户權限是 [ROLE_USER, ROLE_RUN_AS_REPORTER]
  • 臨時 Authentication 對象僅在 .tryRunAS() 方法調用期間替換現有的 Authentication 對象

5. 服務

最後,讓我們實現實際的邏輯——一個同時被保護的簡單服務層:

@Service
public class RunAsService {

    @Secured({ "ROLE_RUN_AS_REPORTER" })
    public Authentication getCurrentUser() {
        Authentication authentication = 
          SecurityContextHolder.getContext().getAuthentication();
        return authentication;
    }
}

請注意:

  • 要訪問 .getCurrentUser() 方法,我們需要 ROLE_RUN_AS_REPORTER 角色
  • 因此,我們只能在 .tryRunAs() 控制器方法內部調用 .getCurrentUser() 方法

6. 前端

接下來,我們將使用一個簡單的前端來測試我們的“運行作為”功能:

<html>
<body>
Current user authorities: 
    <span sec:authentication="principal.authorities">user</span>
<br/>
<span id="temp"></span>
<a href="#" onclick="tryRunAs()">Generate Report As Super User</a>
             
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script type="text/javascript">
function tryRunAs(){
    $.get( "/runas" , function( data ) {
         $("#temp").html(data);
    });
}
</script>
</body>
</html>

現在,當用户觸發“生成報告(超級用户)”操作時,他們將獲得臨時 ROLE_RUN_AS_REPORTER 權限。

7. 結論

在本快速教程中,我們探討了使用 Spring Security 的 “Run-As” 身份驗證替換 功能的一個簡單示例。

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

發佈 評論

Some HTML is okay.