1. 概述
Spring Security 負責處理和解析身份驗證憑據。
在本簡短教程中,我們將學習如何從請求中獲取 SecurityContext 信息,並在我們的處理代碼中實現。
2. @CurrentSecurityContext 註解
我們可以使用一些樣板代碼來讀取安全上下文:
SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();然而,現在有一個 @CurrentSecurityContext 註解可以幫助我們。
此外,使用註解使代碼更具聲明性,並使 認證 對象可注入。通過 @CurrentSecurityContext,我們還可以訪問當前用户的 Principal 實現。
在下面的示例中,我們將探討獲取安全上下文數據的一些方法,例如 Authentication 和 Principal 的名稱。我們還將看到如何測試我們的代碼。
3. Maven 依賴
如果我們的 Spring Boot 版本是較新的,那麼我們只需要包含 spring-boot-starter-security 依賴項即可。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>否則,我們可以包含 spring-security-core:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>6.1.5</version>
</dependency>4. 使用 @CurrentSecurityContext 實現
我們可以使用 Spring 表達式語言 (SpEL) 與 @CurrentSecurityContext 結合,注入 Authentication 對象或 Principal 對象。 SpEL 與類型查找機制協同工作。 默認情況下,類型檢查不會強制執行,但可以通過啓用 errorOnInvalidType 參數來啓用,該參數位於 @CurrentSecurityContext 註解中。
4.1. 獲取 身份驗證 對象
讓我們讀取 身份驗證 對象,以便返回其詳細信息:
@GetMapping("/authentication")
public Object getAuthentication(@CurrentSecurityContext(expression = "authentication")
Authentication authentication) {
return authentication.getDetails();
}
請注意,SpEL表達式引用的是身份驗證 對象本身。
讓我們進行測試:
@Test
public void givenOAuth2Context_whenAccessingAuthentication_ThenRespondTokenDetails() {
ClientCredentialsResourceDetails resourceDetails =
getClientCredentialsResourceDetails("baeldung", singletonList("read"));
OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);
String authentication = executeGetRequest(restTemplate, "/authentication");
Pattern pattern = Pattern.compile("\\{\"remoteAddress\":\".*"
+ "\",\"sessionId\":null,\"tokenValue\":\".*"
+ "\",\"tokenType\":\"Bearer\",\"decodedDetails\":null}");
assertTrue("authentication", pattern.matcher(authentication).matches());
}我們應該注意的是,在這個例子中,我們獲取了連接的所有詳細信息。由於我們的測試代碼無法預測 remoteAddress 或 tokenValue,我們使用正則表達式來檢查生成的 JSON。
4.2. 獲取 Principal
如果僅想從認證數據中獲取 Principal,我們可以修改 SpEL 表達式和注入的 Bean:
@GetMapping("/principal")
public String getPrincipal(@CurrentSecurityContext(expression = "authentication.principal")
Principal principal) {
return principal.getName();
}在這種情況下,我們僅使用 getName 方法返回 Principal 名稱。
讓我們測試一下:
@Test
public void givenOAuth2Context_whenAccessingPrincipal_ThenRespondBaeldung() {
ClientCredentialsResourceDetails resourceDetails =
getClientCredentialsResourceDetails("baeldung", singletonList("read"));
OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);
String principal = executeGetRequest(restTemplate, "/principal");
assertEquals("baeldung", principal);
}在這裏,我們看到名稱 baeldung 被添加到客户端憑據中,並且從 Principal 對象中注入到處理程序中被找到並返回。
5. 結論
在本文中,我們學習瞭如何在當前安全上下文中訪問屬性,並將它們注入到我們的處理方法參數中。
我們通過利用 SpEL 和 @CurrentSecurityContext 註解來實現的。