Разбираем процесс аутентификации Spring Security

Spring

предисловие

Весенняя безопасность должна быть одной из модулей с крутой кривой обучения в весеннем семейном ведре.

Пока я не взял его снова некоторое время назад, после того, как на этот раз я нашел много информации в Интернете, я, наконец, получил определенное представление о Spring Security и обнаружил, что это не так сложно понять.

Вот краткое изложение.

Простой процесс аутентификации

Многие люди должны были использовать следующие методы аутентификации, когда они впервые начали учиться писать веб-приложения:

  1. Интерфейсная страница получает пароль учетной записи пользователя и другую информацию и отправляет ее на серверную часть с помощью запроса POST.
  2. Бэкэнда получает пароль учетной записи пользователя и другую информацию в базу данных для запроса информации о пользователе, сохраненной сервером
  3. Сравните информацию о пользователе в базе данных с информацией о пароле учетной записи, переданной внешним интерфейсом.
  4. Если это то же самое, создайте токен, сохраните его в сеансе и верните токен клиенту.
  5. Внешний интерфейс сохраняет полученный токен и переносит токен в последующих запросах, чтобы подтвердить его личность.

Такой метод аутентификации очень прост, но разве процесс аутентификации в Spring Security не такой? Однако Spring Security реализует такой процесс аутентификации через более унифицированный абстрактный интерфейс.

Spring Security

В предыдущем простом процессе аутентификации некоторые вещи можно абстрагировать как отдельные сущности, и эти сущности могут находить соответствующие объекты в Spring Security, в том числе:

  1. Пароль учетной записи и другая информация, введенная пользователем, эти вещи на самом деле являются информацией о аутентификации пользователя, которая соответствует источнику безопасности.AuthenticationObject, за исключением того, что объект Authentication в Spring Security может использоваться для сохранения подробной информации о пользователе, полученной из базы данных после успешной аутентификации пользователя, в дополнение к информации об аутентификации пользователя.

    public interface Authentication extends Principal, Serializable {
      Collection<? extends GrantedAuthority> getAuthorities();  // 用户权限
      Object getCredentials();                                  // 用户认证信息
      Object getDetails();                                      // 用户详细信息
      Object getPrincipal();                                    // 用户身份信息
      boolean isAuthenticated();                                // 当前 Authentication 是否已认证
      void setAuthenticated(boolean isAuthenticated);
    }
    
  2. Информации для аутентификации, предоставленной пользователем, часто недостаточно, чтобы судить о том, является ли пользователь законным, поэтому нам обычно нужны какие-то средства для получения информации о пользователе, хранящейся на сервере, и в то же время нам также нужны какие-то средства для сохранения информация о пользователе. Они соответствуют Spring SecurityUserDetailsServiceиUserDetailsэти два объекта.

    public interface UserDetailsService {
      UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
    }
    
    public interface UserDetails extends Serializable {
      Collection<? extends GrantedAuthority> getAuthorities();
      String getPassword();
      String getUsername();
      boolean isAccountNonExpired();
      boolean isAccountNonLocked();
      boolean isCredentialsNonExpired();
      boolean isEnabled();
    }
    
  3. После того, как у нас есть информация для аутентификации, предоставленная пользователем, и информация о пользователе, хранящаяся на сервере, нам нужно каким-то образом сравнить две части информации, и объект для проверки информации для аутентификации пользователя соответствует Spring Security.AuthenticationManagerобъект.

    Authentication authenticate(Authentication authentication)throws AuthenticationException;
    

    С учетом множества информации о аутентификации пользователей и бесконечных методов валидации, Spring Security предоставляет интерфейс, который для нас легче расширитьAuthenticationProviderиProviderManagerЭта реализация AuthenticationManager по умолчанию. При использовании нам часто нужно только реализоватьAuthenticationProviderБудет достаточно.

    public interface AuthenticationProvider {
      Authentication authenticate(Authentication authentication) throws AuthenticationException;
      boolean supports(Class<?> authentication);
    }
    

    Как видите, методы в AuthenticationProviderauthenticateвернетAuthenticationОбъект, при аутентификации этот объект часто сохраняет данные пользователя.

  4. Когда информация аутентификации пользователя прошла тест, нам часто нужно сохранить информацию аутентификации или сгенерированный токен на сервере, и объект этой сохраненной информации аутентификации находится в Spring Security.SecurityContextиSecurityContextHolderЭти два объекта: SecurityContext сохраняет аутентифицированный объект Authentication, а SecurityContextHolder сохраняет SecurityContext в контексте текущего потока для нашего удобства.

    public interface SecurityContext extends Serializable {
      Authentication getAuthentication();
      void setAuthentication(Authentication authentication);
    }
    
    public class SecurityContextHolder {
      public static SecurityContext getContext();
      public void SecurityContext setContext();
    }
    

    Spring Security реализован на основе Filter, и каждому запросу часто назначается поток, поэтому до того, как запрос достигнет определенной логики обработки, Spring Security может завершить аутентификацию информации о пользователе в Filter и сгенерировать последующее использование SecurityContext.

Вот источник изSpring Security (1) — Обзор архитектуры | Исходный код Taro — Блог о чистом анализе исходного кодаИзображение , которое хорошо объясняет взаимосвязь между вышеуказанными объектами:

Видно, что, хотя Spring Security кажется сложным, его основная идея остается такой же, как и в предыдущем простом процессе аутентификации. Однако Spring Security абстрагирует ключевые части и предоставляет соответствующие интерфейсы расширения.

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

Конечно, в Spring Security больше функций, но после определенного понимания основного процесса последующее содержание можно изучить легче.

Эпилог

На самом деле, в дополнение к Spring Security, я также взглянул на Spring Security OAuth2 и Spring Security JWT, Я чувствовал, что могу обобщить это с помощью этого блога, но когда я написал его, я обнаружил, что идея Часть Spring Security настолько ясна, как вы попали в Spring?После Security OAuth2 она стала прерывистой.

Потом я отправил письмо, но примерно разъяснил взаимосвязь между Spring Security и Spring Security OAuth2, а детали еще предстоит изучить, так что оставлю это на будущее @_@

Ссылка на ссылку