1. 概述
在本教程中,我們將演示如何在 Spring Security 中使用 Run-As 身份驗證,並使用一個簡單的場景。
Run-As 的高層次解釋如下:用户可以以具有不同特權的另一個主體執行一些邏輯。
2. The 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 context 中,替換默認實現,該實現返回 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;
}
我們當然使用與管理器中相同的密鑰進行設置,以便提供者可以驗證 RunAsUserTokenAuthentication對象是否使用相同的密鑰創建。
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 "當前用户權限在 RunAS 方法內僅限於 " +
auth.getAuthorities().toString();
}
}
關鍵在於新的角色 – RUN_AS_REPORTER
這是 Run-As 功能的觸發器,因為框架由於前綴的不同而以不同的方式處理它。
當請求通過此邏輯執行時,我們將有:
- 在 tryRunAs() 方法之前,當前用户權限為 [ROLE_USER]
- 在 tryRunAs() 方法內部,當前用户權限為 [ROLE_USER, ROLE_RUN_AS_REPORTER]
- 臨時 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()方法
接下來,我們將使用一個簡單的前端來測試我們的“運行作為”功能:
<html>
<body>
當前用户權限:
<span sec:authentication="principal.authorities">用户</span>
<br/>
<span id="temp"></span>
<a href="#" onclick="tryRunAs()">生成報告作為超級用户</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 的 “以指定用户身份運行”身份驗證替換 功能。