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

Получить информацию о пользователе в Spring Security

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

Задача: Наибольшая подстрока без повторений

Для заданной строки s, найдите длину наибольшей подстроки без повторяющихся символов. Подстрока — это непрерывная непустая последовательность символов внутри строки...

ANDROMEDA 42

1. Обзор

В этом руководстве показано, как получить данные пользователя в Spring Security.

Текущий аутентифицированный пользователь доступен в Spring через ряд различных механизмов. Давайте сначала рассмотрим наиболее распространенное решение — программный доступ.

2. Получите пользователя в компоненте

Самый простой способ получить текущего аутентифицированного принципала — это статический вызов SecurityContextHolder :

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String currentPrincipalName = authentication.getName();

Улучшение этого фрагмента заключается в том, что перед попыткой доступа к нему сначала проверяется наличие аутентифицированного пользователя:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication instanceof AnonymousAuthenticationToken)) {
String currentUserName = authentication.getName();
return currentUserName;
}

Конечно, у такого статического вызова есть недостатки, и снижение тестируемости кода является одним из наиболее очевидных. Вместо этого мы рассмотрим альтернативные решения для этого очень распространенного требования.

3. Получите пользователя в контроллере

У нас есть дополнительные параметры в аннотированном bean -компоненте @Controller .

Мы можем определить принципала напрямую как аргумент метода , и он будет корректно разрешен фреймворком:

@Controller
public class SecurityController {

@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserName(Principal principal) {
return principal.getName();
}
}

В качестве альтернативы мы также можем использовать токен аутентификации :

@Controller
public class SecurityController {

@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserName(Authentication authentication) {
return authentication.getName();
}
}

API класса Authentication очень открытый, поэтому фреймворк остается максимально гибким. Из-за этого субъект Spring Security может быть получен только как объект и должен быть приведен к правильному экземпляру UserDetails :

UserDetails userDetails = (UserDetails) authentication.getPrincipal();
System.out.println("User has authorities: " + userDetails.getAuthorities());

И, наконец, вот прямо из HTTP-запроса :

@Controller
public class GetUserWithHTTPServletRequestController {

@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserNameSimple(HttpServletRequest request) {
Principal principal = request.getUserPrincipal();
return principal.getName();
}
}

4. Получить пользователя через пользовательский интерфейс

Чтобы полностью использовать внедрение зависимостей Spring и иметь возможность получать аутентификацию везде, а не только в компонентах @Controller , нам нужно скрыть статический доступ за простым фасадом:

public interface IAuthenticationFacade {
Authentication getAuthentication();
}
@Component
public class AuthenticationFacade implements IAuthenticationFacade {

@Override
public Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
}

Фасад предоставляет объект Authentication , скрывая статическое состояние и сохраняя код несвязанным и полностью тестируемым:

@Controller
public class GetUserWithCustomInterfaceController {
@Autowired
private IAuthenticationFacade authenticationFacade;

@RequestMapping(value = "/username", method = RequestMethod.GET)
@ResponseBody
public String currentUserNameSimple() {
Authentication authentication = authenticationFacade.getAuthentication();
return authentication.getName();
}
}

5. Получить пользователя в JSP

Доступ к текущему аутентифицированному принципалу также можно получить на страницах JSP , используя поддержку Spring Security Taglib.

Во-первых, нам нужно определить тег на странице:

<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

Далее мы можем обратиться к принципалу :

<security:authorize access="isAuthenticated()">
authenticated as <security:authentication property="principal.username" />
</security:authorize>

6. Получите пользователя в Thymeleaf

Thymeleaf — это современный механизм веб-шаблонов на стороне сервера с хорошей интеграцией с инфраструктурой Spring MVC .

Давайте посмотрим, как получить доступ к текущему аутентифицированному принципалу на странице с движком Thymeleaf.

Во- первых, нам нужно добавить зависимости thymeleaf-spring5 и thymeleaf-extras-springsecurity5 для интеграции Thymeleaf со Spring Security:

<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>

Теперь мы можем ссылаться на принципала на HTML-странице с помощью атрибута sec:authorize :

<html xmlns:th="https://www.thymeleaf.org" 
xmlns:sec="https://www.thymeleaf.org/thymeleaf-extras-springsecurity5">
<body>
<div sec:authorize="isAuthenticated()">
Authenticated as <span sec:authentication="name"></span></div>
</body>
</html>

7. Заключение

В этой статье показано, как получить информацию о пользователе в приложении Spring, начиная с общего статического механизма доступа, за которым следует несколько более эффективных способов внедрения принципала.

Реализацию этих примеров можно найти в проекте GitHub . Это проект на основе Eclipse, поэтому его легко импортировать и запускать как есть. При локальном запуске проекта мы можем получить доступ к HTML-коду домашней страницы здесь:

http://localhost:8080/spring-security-rest-custom/foos/1