Использование методов stati c в Spring Security для получения текущих сведений о пользователе - PullRequest
3 голосов
/ 02 мая 2020

У меня есть требование, чтобы получить информацию о текущем пользователе, который вошел в систему. Чтобы получить детали, мы можем использовать 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.

1 Ответ

1 голос
/ 02 мая 2020

Настройка

.sessionManagement()
     .sessionCreationPolicy(SessionCreationPolicy.STATELESS)

приведет к Spring Security с использованием NullSecurityContextRepository вместо значения по умолчанию HttpSessionSecurityContextRepository.

Это простая реализация, в которой она просто ничего не сохраняет в сеансе HTTP и при каждом запросе создает полностью new and empty SecurityContext, следовательно, без сохраненной аутентификации и т. Д. c.

Итак, отвечая на ваш первый вопрос:

SecurityContextPersistenceFilter будет работать так же, как и с HttpSessionRepository, другой ручной настройки не требуется.

Чтобы ответить на ваш второй и третий вопрос, касающийся Threadlocals.

Да, в этом весь смысл их использования, и в любом случае это стратегия по умолчанию. Таким образом, каждый поток имеет свои собственные объекты SecurityContext / Authentication. Вы обращаетесь к ThreadLocal с помощью вашего метода stati c, следовательно, у вас нет шансов получить доступ к «неправильным» данным пользователя. Было бы проблемой использовать GlocalSecurityContextHolderStrategy в вашем случае использования, но это не то, что вы делаете, в любом случае.

Кроме того, имейте в виду, что все это не имеет ничего общего с @ Transactionals.

...