Введение
Доброго времени суток, друзья!
В данной статье я постараюсь довольно кратко и подробно описать то, как работает spring security изнутри. Статья будет вводная, и будет содержать в основном теорию.
Собственно. Что же такое этот Spring Security?
Spring Security — это главный фреймворк который предоставляет механизмы построения систем аутентификации и авторизации. Помимо этого он даёт возможность обеспечения безопасности для приложений, созданных на spring’e.
Мы поняли, что он обеспечивает безопасность и даёт возможность аутентификации и авторизации, то что это такое?…
Аутентификация — это проверка личности пользователя, то есть логин+пароль или jwt или к примеру OAuth2. Если проще, то аутентификация отвечает на вопрос: «Докажи что ты это ты?»Авторизация — это проверка прав доступа, то есть то, что конкретный пользователь может делать. Например, обычный пользователь может посмотреть список продуктов, добавить продукты в корзину и сделать заказ. А в это время менеджер может сделать всё то же самое, что и обычный пользователь, но и добавить и/или убрать каике то товары из магазина. Снова для простоты, авторизация отвечает на вопрос: «Что тебе можно делать?»
Далее возникает вопрос: а как оно работает?
Ответ на этот вопрос довольно прост. Spring Security перехватывает каждый HTTP‑запрос с помощью специальных Servlet Filter‑ов, которые встраиваются в жизненный цикл HTTP‑запроса до того, как он доберётся до контроллера.
Чуть ниже будет картинка как работает эта магия, но ничего магического там нет, всё на себя берёт проксирование. И чтобы понять эту картинку, нужно узнать пару новых вещей:
DelegatingFilterProxy — это такой своеобразный мост между Servlet Api и Spring context. Он позволяет перенаправить входящие HTTP‑запросы на обработку компонентами, которыми управляет сам Spring.FilterChainProxy — это специальный связующий фильтр (прокси), который управляет всеми цепочками фильтров.SecurityFilterChain — по сути это цепочка обработки HTTP‑запроса, то есть каждый запрос проходит определённые проверки, например на определённые url может заходить только админ и тп.
После того как пользователь успешно пройдёт аутентификацию Spring Security сохраняет пользователя в SecurityContext:
SecurityContext context = SecurityContextHolder.getContext();//Объект аутентификаации который содержит информацию о вошедешем пользователеAuthentication auth = context.getAuthentication();//Получение уникального имени пользователяString username = auth.getName();//Получение списка ролей, выданных пользователюCollection<? extends GrantedAuthority> roles = auth.getAuthorities();
Важно добавить, что сам SecurityContextHolder по умолчанию использует ThreadLocal — это значит что контекст живёт в рамках одного потока запросов. Это одновременно и хорошо и не очень.
Это хорошо потому что — данные о пользователе можно получить из любого сервиса или репозитория без необходимости передачи Authentication через аргументы всех вызовов, а также привязка к потоку гарантирует, что запросы пользователей не смешаются между собой и пользователь А не увидит данные пользователя Б.
А не очень хорошо потому что при каких либо асинхронных фоновых задач, SecurityContext не будет скопирован в новый поток, что может вести за собой падение методов с @PreAuthorize или @Sheduled, а также могут возникнуть ошибки при работе с базами данных, пустыми отчётами и так далее.
Дабы избежать неприятных моментов, можно изменить стратегию хранения SecurityContextHolder, чтобы адаптировать под свои нужды, но это уже как-нибудь потом.
Спасибо всем кто дочитал эту статью, надеюсь она оказалась полезной и информативной. Если эту статью из интереса прочитает более опытный человек, то с радостью приму критику и учту в дальнейших статьях!
ссылка на оригинал статьи https://habr.com/ru/articles/1054852/