Spring безопасность SecurityContextHolder: привязка сеанса или запроса?

Является ли UserPrincipal я извлекаю из SecurityContextHolder для запросов или сеансов?

UserPrincipal principal = (UserPrincipal) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

Так я могу получить доступ к текущему пользователю. Будет ли это недействительным, если текущий сеанс будет уничтожен?

Ответ 1

Это зависит от того, как вы его настроили (или, скажем, вы можете настроить другое поведение).

В веб-приложении вы будете использовать ThreadLocalSecurityContextHolderStrategy, который взаимодействует с SecurityContextPersistenceFilter.

Java Doc SecurityContextPersistenceFilter начинается с:

Заполняет {@link SecurityContextHolder} с информацию, полученную из настроен {@link SecurityContextRepository} до запрос и сохраняет его обратно в если запрос имеет завершено и очищено контекст держатель. По умолчанию используется {@link HttpSessionSecurityContextRepository}. См. Этот класс для информации Связанный с HttpSession конфигурации.

Btw: HttpSessionSecurityContextRepository - единственная реализация SecurityContextRepository (я нашел в папках по умолчанию)

Он работает следующим образом:

  • HttpSessionSecurityContextRepository использует httpSession (Key = "SPRING_SECURITY_CONTEXT" ) для хранения объекта SecurityContext.
  • SecurityContextPersistenceFilter - это фильтр, который использует SecurityContextRepository, например, HttpSessionSecurityContextRepository для загрузки и хранения объектов SecurityContext. Если HttpRequest передает фильтр, фильтр получает SecurityContext из репозитория и помещает его в SecurityContextHolder (SecurityContextHolder#setContext)
  • SecurityContextHolder имеет два метода setContext и getContext. Оба используют SecurityContextHolderStrategy, чтобы указать, что именно делается в методах set и get-Context. - Например, ThreadLocalSecurityContextHolderStrategy использует локальный поток для хранения контекста.

Итак, вкратце: главный пользователь (элемент SecurityContext) хранится в сеансе HTTP. И для каждого запроса он помещается в поток локальный, откуда вы обращаетесь к нему.