Перейти к основному содержимому

Spring Security: аутентификация с помощью UserDetailsService на базе базы данных

· 4 мин. чтения

1. Обзор

В этой статье мы покажем, как создать пользовательскую службу UserDetailsService с поддержкой базы данных для аутентификации с помощью Spring Security.

2. Служба сведений о пользователе

Интерфейс UserDetailsService используется для получения данных, связанных с пользователем. Он имеет один метод с именем loadUserByUsername() , который можно переопределить, чтобы настроить процесс поиска пользователя.

Он используется DaoAuthenticationProvider для загрузки сведений о пользователе во время аутентификации.

3. Пользовательская модель

Для хранения пользователей мы создадим сущность User , сопоставленную с таблицей базы данных, со следующими атрибутами:

@Entity
public class User {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;

@Column(nullable = false, unique = true)
private String username;

private String password;

// standard getters and setters
}

4. Получение пользователя

Для получения пользователя, связанного с именем пользователя, мы создадим класс DAO , используя Spring Data , расширив интерфейс JpaRepository :

public interface UserRepository extends JpaRepository<User, Long> {

User findByUsername(String username);
}

5. Служба сведений о пользователе

Чтобы предоставить собственный пользовательский сервис, нам потребуется реализовать интерфейс UserDetailsService .

Мы создадим класс с именем MyUserDetailsService , который переопределяет метод интерфейса loadUserByUsername() .

В этом методе мы извлекаем объект User с помощью DAO и, если он существует, оборачиваем его в объект MyUserPrincipal , реализующий UserDetails , и возвращаем его:

@Service
public class MyUserDetailsService implements UserDetailsService {

@Autowired
private UserRepository userRepository;

@Override
public UserDetails loadUserByUsername(String username) {
User user = userRepository.findByUsername(username);
if (user == null) {
throw new UsernameNotFoundException(username);
}
return new MyUserPrincipal(user);
}
}

Давайте определим класс MyUserPrincipal следующим образом:

public class MyUserPrincipal implements UserDetails {
private User user;

public MyUserPrincipal(User user) {
this.user = user;
}
//...
}

6. Конфигурация пружины

Мы продемонстрируем оба типа конфигураций Spring: XML и на основе аннотаций, которые необходимы для использования нашей пользовательской реализации UserDetailsService .

6.1. Конфигурация аннотации

Все, что нам нужно сделать, чтобы включить нашу пользовательскую службу UserDetailsService , — это добавить ее в контекст нашего приложения в виде bean-компонента.

Поскольку мы настроили наш класс с аннотацией @Service , приложение автоматически обнаружит его во время сканирования компонентов и создаст bean-компонент из этого класса. Поэтому здесь больше ничего делать не нужно.

В качестве альтернативы мы можем:

  • настройте его в authenticationManager , используя метод AuthenticationManagerBuilder #userDetailsService.
  • установите его как свойство в пользовательском bean-компоненте authenticationProvider , а затем внедрите его с помощью функции AuthenticationManagerBuilder # authenticationProvider .

6.2. XML-конфигурация

С другой стороны, для конфигурации XML нам нужно определить bean-компонент с типом MyUserDetailsService и внедрить его в bean -компонент поставщика аутентификации Spring :

<bean id="myUserDetailsService" 
class="org.foreach.security.MyUserDetailsService"/>

<security:authentication-manager>
<security:authentication-provider
user-service-ref="myUserDetailsService" >
<security:password-encoder ref="passwordEncoder">
</security:password-encoder>
</security:authentication-provider>
</security:authentication-manager>

<bean id="passwordEncoder"
class="org.springframework.security
.crypto.bcrypt.BCryptPasswordEncoder">
<constructor-arg value="11"/>
</bean>

7. Другие варианты аутентификации на основе базы данных

AuthenticationManagerBuilder предлагает еще один метод настройки аутентификации на основе JDBC в нашем приложении .

Нам нужно настроить AuthenticationManagerBuilder.jdbcAuthentication с экземпляром DataSource . Если наша база данных следует Spring User Schema , то конфигурации по умолчанию нам вполне подойдут.

Мы видели базовую конфигурацию с использованием этого подхода в предыдущем посте .

Объект JdbcUserDetailsManager , полученный в результате этой конфигурации, также реализует UserDetailsService .

В результате мы можем сделать вывод, что эту конфигурацию проще реализовать, особенно если мы используем Spring Boot, который автоматически настраивает для нас DataSource .

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

8. Заключение

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

Реализацию можно найти в проекте GitHub — это проект на основе Maven, поэтому его легко импортировать и запускать как есть.