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, поэтому его легко импортировать и запускать как есть.