У меня есть требование, чтобы получить информацию о текущем пользователе, который вошел в систему. Чтобы получить детали, мы можем использовать SecurityContextHolder.getContext()
и извлечь детали. В соответствии с
SecurityContextHolder, SecurityContext и объекты аутентификации
По умолчанию SecurityContextHolder
использует ThreadLocal
для хранения эти детали, что означает, что контекст безопасности всегда доступен для методов в том же потоке выполнения . Использование ThreadLocal
таким образом - quite safe if care is taken to clear the thread after the present principal’s request is processed
. Конечно, Spring Security позаботится об этом автоматически, поэтому вам не нужно об этом беспокоиться.
Хранение SecurityContext между запросами
В Spring Security ответственность за хранение SecurityContext
между запросами ложится на SecurityContextPersistenceFilter
, который по умолчанию сохраняет контекст как атрибут HttpSession
между HTTP-запросами . Он восстанавливает контекст до SecurityContextHolder
для каждого запроса и, что особенно важно, очищает SecurityContextHolder, когда запрос завершает
Многие другие типы приложений (например, RESTful без состояния) * Веб-служба ) не использует сеансов HTTP и будет проходить повторную проверку подлинности при каждом запросе . Однако по-прежнему важно, чтобы SecurityContextPersistenceFilter
был включен в цепочку, чтобы гарантировать, что SecurityContextHolder
очищается после каждого запроса.
Вопрос -
Мне потребовались данные пользователя в нескольких местах на уровне сервиса, чтобы вернуть информацию на основе полномочий пользователя, поэтому у нас есть один метод stati c, который возвращает эти данные. Проект состоит из REST API и политики создания сеансов как SessionCreationPolicy.STATELESS
с SecurityContextHolderStrategy
как ThreadLocal
. Уровень обслуживания состоит из @Transactional
.
Теперь рассмотрим несколько одновременных запросов к API,
- Как Spring Security будет управлять
SecurityContextPersistenceFilter
для STATELESS приложений, требуются ли ручные настройки? - Можно ли использовать
SecurityContextHolderStrategy
как ThreadLocal
? - Есть ли вероятность получить неправильные / неверные данные пользователя из-за стратегии
ThreadLocal
и метода stati c?
Среда:
Каркас: Spring Boot
ORM: Hibernate
База данных: Postgres
Архитектура: Monolithi c ( который собирается перейти на микросервисы)
Я добавлю больше деталей, если потребуется
ОБНОВЛЕНИЕ:
Спасибо @Macro, как уже упоминалось, за SessionCreationPolicy.STATELESS
,
SessionManagementConfigurer
, состоящий из isStateless()
метода, который возвращает true для политики без сохранения состояния. На основании этого http установите общий объект с NullSecurityContextRepository
и для кеша запросов NullRequestCache
. Следовательно, никакое значение не будет доступно в HttpSessionSecurityContextRepository
. Таким образом, не может быть проблемы с неверными / неправильными данными для пользователя с stati c method
- Влияет ли
SecurityContextHolderStrategy
на детали пользователя с MODE_INHERITABLETHREADLOCAL, MODE_THREADLOCAL как для общего объекта не будет установлено значение HttpSessionSecurityContextRepository
?
Код:
if (stateless) {
http.setSharedObject(SecurityContextRepository.class,
new NullSecurityContextRepository());
}
if (stateless) {
http.setSharedObject(RequestCache.class, new NullRequestCache());
}
Код:
stati c метод получения сведений о пользователе
public static Optional<String> getCurrentUserLogin() {
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(extractPrincipal(securityContext.getAuthentication()));
}
private static String extractPrincipal(Authentication authentication) {
if (authentication == null) {
return null;
} else if (authentication.getPrincipal() instanceof UserDetails) {
UserDetails springSecurityUser = (UserDetails) authentication.getPrincipal();
return springSecurityUser.getUsername();
} else if (authentication.getPrincipal() instanceof String) {
return (String) authentication.getPrincipal();
}
return null;
}
public static Optional<Authentication> getAuthenticatedCurrentUser() {
log.debug("Request to get authentication for current user");
SecurityContext securityContext = SecurityContextHolder.getContext();
return Optional.ofNullable(securityContext.getAuthentication());
}
sessionManagement
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
Примечания
SecurityContextHolderStrategy as ThreadLocal
Уровень обслуживания состоит из @Transactional
.