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 .