Аутентификация в памяти с весенней загрузкой, вероятно, самый простой способ реализовать аутентификацию. Как показано на рисунке ниже, я попытаюсь объяснить несколько различных способов реализации аутентификации в памяти.

Во-первых, давайте создадим простой элемент управления REST и скажем «Привет» 😃. И попробуйте позвонить в конечную точку.

Да, я получаю ошибку 401, потому что я включил безопасность, но без какой-либо действительной аутентификации. (см. часть 01 этой статьи, чтобы узнать о включении безопасности)

Вы, возможно, задавались вопросом, когда мы вызываем веб-страницу через браузер, она перенаправляет страницу входа в систему, но когда мы вызываем из таких инструментов, как «Почтальоны», она просто возвращает сообщение «Неавторизовано».

Это связано с тем, что Spring сопоставляет запрос с «RequestMatcher», который связывается с каждой точкой входа перед отправкой запроса в точку входа.

«MediaTypeRequestMatcher» является одним из ассоциированных «RequestMatcher» для «LoginUrlAuthenticationEntryPoint». Поэтому, когда мы делаем запрос через почтальонов, заголовок «Принять» по умолчанию не установлен.

Итак, поскольку для параметра «Принять» не задано значение «текст / html», запрос не достигает «LoginUrlAuthenticationEntryPoint», который обслуживает содержимое HTML, поскольку тип MediaType не соответствует.

Итак, теперь я собираюсь настроить механизм аутентификации, чтобы пользователь аутентифицировался перед вызовом конечной точки. Для этого вам необходимо переопределить «WebSecurityConfigurer». но более практичный способ - переопределить «WebSecurityConfigurerAdapter».

Здесь переопределите метод «configure» и установите для «anyRequest» значение «Authenticated».

Также здесь я не настраивал «formLogin», поэтому теперь «FormLoginConfigurer» неприменим, поэтому больше не будет LoginUrlAuthenticationEntryPoint, который ведет к DefaultLoginPageGeneratingFilter и отрисовывает страницу входа.

Теперь мы можем приступить к реализации аутентификации в памяти.

1. Использование «AuthenticationManager»

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

Примечание: - Здесь я использовал «NoOpPasswordEncoder», чтобы показать, как установить имя пользователя и пароль. «NoOpPasswordEncoder» уже устарел, потому что он не защищен. Вместо этого мы можем использовать другой тип «PasswordEncoder». (Пример: BCryptPasswordEncoder). Итак, полный код выглядит так.

Посмотрим, как это работает.

При определении «inMemoryAuthentication» весь «WebSecurityConfigurer» применяется к конфигурации «InMemoryUserDetailsManagerConfigurer», которая является другой реализацией «UserDetailsAwareConfigurer».

Любой UserDetailsAwareConfigurer связан с UserDetailsService, который взаимодействует и используется для получения данных, связанных с пользователем. В этом случае это служба, которая отвечает за получение «UserDetails» для данного имени пользователя. С InMemoryUserDetailsManagerConfigurer, InMemoryUserDetailsManager будет UserDetailsService. (одна из реализаций UserDetailsService. А также еще одна распространенная служба userdetail - JdbcUserDetailsManager, которая поставляется с конфигурацией JDBC).

Тогда по умолчанию «DaoAuthenticationProvider» работает как «AuthenticationProvider» по умолчанию для любого «UserDetailsAwareConfigurer».

Итак, как только запрос попадает в «AuthenticationManager» из любого фильтра, связанного с аутентификацией, он пытается аутентифицировать запрос через поддерживаемый «AuthenticationProvider».

для этого экземпляра поддерживаемый провайдер - «DaoAuthenticationProvider». Таким образом, провайдер несет ответственность за предоставление правильного «пользователя» и связанных с ним аутентифицированных данных.

поэтому сначала провайдер начинает получать пользователя, давая имя пользователя. для этого провайдер использует связанный с ним UserDetailsService для загрузки пользователя. (помните, что в этом случае служба UserDetail - это InMemoryUserDetailsManager).

@ см. UserDetailsService.loadUserByUsername ()

Поскольку мы предоставляем имя пользователя и пароль через конфигурацию, эти значения хранятся в HashMap в InMemoryUserDetailsManager.

После загрузки «UserDetails» через «UserDetailsService» он сопоставляет пароль, используя заданный кодировщик паролей. Если он совпадает, то успешная аутентификация (например, токен) обновит SecurityContextHolder, а затем позволит выполнять другие фильтры в FilterChainProxy. Затем, в конце концов, после всех проверок безопасности, запрос передается в «DispatcherServlet» для поиска подходящего контроллера и его сопоставления, а затем после выполнения содержимого.

2. Использование настраиваемого «AuthenticationProvider»

Хорошо, прежде чем приступить к реализации, позвольте мне немного подробнее рассказать о «ProviderManager» и «AuthenticationProviders».

ProviderManager - одна из наиболее распространенных реализаций AuthenticationManager. Если только мы не создадим собственный «AuthenticationManager». «AuthenticationManagerBuilder» по умолчанию создает «ProviderManager». «ProviderManager» содержит список «AuthenticationProviders», и после того, как AuthenticationFilter вызывает метод аутентификации, «ProviderManager» выполняет итерацию всех «AuthenticationProviders» до тех пор, пока не найдет какого-либо поставщика поддержки для аутентификации запроса.

Здесь мы добавляем настраиваемого поставщика аутентификации. Итак, как я упоминал выше, «как только запрос попадает в« AuthenticationManager »из любого фильтра, связанного с аутентификацией, он пытается аутентифицировать запрос через поддерживаемый« AuthenticationProvider »».

Здесь, в моем пользовательском «AuthenticationProvider», я переопределяю метод аутентификации и проверяю пользователя.

Как только «принципал» и его «учетные данные» верны, создайте успешную аутентификацию и верните (в этом случае токен с именем пользователя, паролем и предоставленными полномочиями)

Примечание. - Поскольку я написал свой собственный AuthenticationProvider, я могу делать все, что угодно, для проверки пользователя, который пытается войти в систему. Даже здесь я не использовал какой-либо UserDetailsService для получения UserDetails, я просто проверил имя пользователя и необработал пароль, который пользователь ввел для аутентификации.

3. Использование «Userdetail»

Прежде всего, UserDetailsService не является компонентом, который принимает решение об аутентификации. Это всего лишь сервис, который помогает получить данные о пользователях для провайдеров аутентификации. Установив настраиваемую службу подробных сведений о пользователях, мы можем сохранить использование в памяти, а затем вернуться по запросу поставщика.

Итак, как я упоминал ранее, с «InMemoryUserDetailsManagerConfigurer», «DaoAuthenticationProvider» работает как провайдер аутентификации по умолчанию, связанный с моим настраиваемым «UserDetailsService».

Здесь я реализую интерфейс «UserDetailsService» и сохраняю использование в памяти, затем, как только провайдер вызывает метод loadUserByUsername, он соответственно возвращает пользователя.

Кроме того, мы можем расширить InMemoryUserDetailsManager и сделать то же самое. Это дает некоторые дополнительные функции, такие как createUser, deleteUser и updatePassword в памяти.

Вот мой SecurityConfig для пользовательского «UserDetailsService»

В следующей части, прежде чем мы перейдем к аутентификации JDBC, давайте разберемся с аутентификацией SuccessHandlers, FailureHandler и EntryPoints.

До следующей части чао !!! ✋

Часть 01