Перейти к основному содержимому

Руководство по @CurrentSecurityContext в Spring Security

· 3 мин. чтения

1. Обзор

Spring Security обрабатывает для нас получение и анализ учетных данных для аутентификации.

В этом кратком руководстве мы рассмотрим, как получить информацию о SecurityContext из запроса в коде нашего обработчика.

2. Аннотация @CurrentSecurityContext

Мы могли бы использовать шаблонный код для чтения контекста безопасности:

SecurityContext context = SecurityContextHolder.getContext();
Authentication authentication = context.getAuthentication();

Однако теперь есть аннотация @CurrentSecurityContext , которая нам поможет .

Кроме того, использование аннотаций делает код более декларативным и позволяет внедрять объект аутентификации . С помощью @CurrentSecurityContext мы также можем получить доступ к основной реализации текущего пользователя.

В приведенных ниже примерах мы рассмотрим несколько способов получения данных контекста безопасности, таких как 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 до минимальной версии 5.2.1.RELEASE:

<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-core</artifactId>
<version>5.2.1.RELEASE</version>
</dependency>

4. Реализация с помощью @CurrentSecurityContext

Мы можем использовать SpEL (язык выражений Spring) с @CurrentSecurityContext для внедрения объекта Authentication или Principal . SpEL работает вместе с поиском типа. Проверка типа не применяется по умолчанию, но мы можем включить ее с помощью параметра errorOnInvalidType аннотации @CurrentSecurityContext .

4.1. Получение объекта аутентификации

Давайте прочитаем объект Authentication , чтобы мы могли вернуть его детали:

@GetMapping("/authentication")
public Object getAuthentication(@CurrentSecurityContext(expression = "authentication")
Authentication authentication) {
return authentication.getDetails();
}

Обратите внимание, что выражение SpEL относится к самому объекту аутентификации .

Давайте проверим это:

@Test
public void givenOAuth2Context_whenAccessingAuthentication_ThenRespondTokenDetails() {
ClientCredentialsResourceDetails resourceDetails =
getClientCredentialsResourceDetails("foreach", 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. Получение принципала

Если нам нужен только Принципал из наших данных аутентификации, мы можем изменить выражение SpEL и внедренный объект:

@GetMapping("/principal")
public String getPrincipal(@CurrentSecurityContext(expression = "authentication.principal")
Principal principal) {
return principal.getName();
}

В этом случае мы возвращаем только имя участника с помощью метода getName . ``

Давайте проверим это:

@Test
public void givenOAuth2Context_whenAccessingPrincipal_ThenRespondForEach() {
ClientCredentialsResourceDetails resourceDetails =
getClientCredentialsResourceDetails("foreach", singletonList("read"));
OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails);

String principal = executeGetRequest(restTemplate, "/principal");

assertEquals("foreach", principal);
}

Здесь мы видим, что имя foreach , которое было добавлено к учетным данным клиента, найдено и возвращено внутри объекта Principal , внедренного в обработчик.

5. Вывод

В этой статье мы увидели, как получить доступ к свойствам в текущем контексте безопасности и внедрить их в параметры в наших методах-обработчиках.

Мы сделали это, воспользовавшись преимуществами SpEL и аннотации @CurrentSecurityContext .

Как всегда, полный исходный код примеров доступен на GitHub .