Получение информации о пользователе - Spring Security в деталях
Зачастую при реализации какой-то функциональности в приложении требуется доступ к информации о текущем аутентифицированном пользователе. Spring Security предоставляет несколько способов получения информации о пользователе, предлагаю их рассмотреть в этой статье.
Универсальный способ
Универсальный для всех веб-приложений на основе Servlet API способ заключается в использовании метода HttpServletRequest.getUserPrincipal(). Данный метод возвращает экземпляр Principal, но в случае со Spring Security всегда будет возвращаться Authentication. Чтобы получить информацию о пользователе из Authentication достаточно вызвать метод getPrincipal() и привести результат к нужному типу.
В приложении на основе Spring Framework это всё будет выглядеть следующим образом:
class GreetingsRestController {
String getGreetings(HttpServletRequest request) {
// Получаем результат аутентификации
var authentication = (Authentication) request.getUserPrincipal();
// Получаем информацию о пользователе
var userDetails = (UserDetails) authentication.getPrincipal();
// Используем
return "Hello %s!".formatted(userDetails.getUsername());
}
}Аналогичным способом можно получить доступ к информации о пользователе в функциональных обработчиках запросов:
class GetGreetingsHandlerFunction
implements HandlerFunction<ServerResponse> {
public ServerResponse handle(ServerRequest request) {
// Получаем результат аутентификации
var userDetails = request.getPrincipal()
// Приводим к Authentication
.map(Authentication.class::cast)
// Получаем информацию о пользователе
.map(Authentication::getPrincipal)
// Приводим к UserDetails
.map(UserDetails.class::cast)
.orElseThrow();
return ServerResponse.ok()
.body("Hello %s!".formatted(userDetails.getUsername()));
}
}Использование контекста безопасности
Ничто не мешает вам в нужном классе обратиться к контексту безопасности. Сделать это можно как через стратегию, так и через класс SecurityContextHolder.
Использование стратегии:
class GreetingsRestController {
SecurityContextHolderStrategy strategy =
SecurityContextHolder.getContextHolderStrategy();
String getGreetings() {
// Получаем информацию о пользователе
var userDetails = (UserDetails) this.strategy.getContext()
.getAuthentication().getPrincipal();
// Используем
return "Hello %s!".formatted(userDetails.getUsername());
}
}Использование SecurityContextHolder:
class GreetingsRestController {
String getGreetings() {
// Получаем информацию о пользователе
var userDetails = (UserDetails) SecurityContextHolder
.getContext().getAuthentication().getPrincipal();
// Используем
return "Hello %s!".formatted(userDetails.getUsername());
}
}Интеграция со Spring Framework
В Spring Framework ожидаемо есть интеграция со Spring Security, благодаря чем информацию о пользователе можно получать в качестве аргументов методов аннотированных контроллеров.
Так любой метод аннотированного контроллера может получать в качестве одного из аргументов объект Principal:
class GreetingsRestController {
String getGreetings(Principal principal) {
// Получение результата аутентификации
var authentication = (Authentication) principal;
// Получаем информацию о пользователе
var userDetails = (UserDetails) authentication.getPrincipal();
// Используем
return "Hello %s!".formatted(userDetails.getUsername());
}
}Но, поскольку при использовании Spring Security это всегда будет Authentication, можно получать аргумент этого типа:
class GreetingsRestController {
String getGreetings(Authentication authentication) {
// Получаем информацию о пользователе
var userDetails = (UserDetails) authentication.getPrincipal();
// Используем
return "Hello %s!".formatted(userDetails.getUsername());
}
}Кроме этого Spring Framework позволяет получать в качестве одного из аргументов метода сразу информацию о пользователе, но этот аргумент должен быть отмечен аннотацией @AuthenticationPrincipal. В этом случае Spring Framework сам получит объект с информацией о пользователе из Authentication и попытается привести его к типу аргумента:
class GreetingsRestController {
String getGreetings(@AuthenticationPrincipal UserDetails userDetails) {
// Используем
return "Hello %s!".formatted(userDetails.getUsername());
}
}Понравилась статья? Тогда поддержки проект и подкинь монетку:
Больше полезных статей и роликов:
