Введение. Зачем я вообще это пишу?

Эта статья является первой, написанной мной. Буду очень рад, если она все же будет опубликована. На данный момент являюсь Junior Java разработчиком, поэтому в этой статье не будет сложной аналитики и глубокого погружения в тему, но я свой опыт изучения и реализации приложений с использованием Spring Security, возможно, кому-то это поможет справиться с теми трудностями, с которыми встретился я.

Недавно мне пришлось подключать и настраивать авторизацию через Spring Security версии 3.1.0. В процессе разработки и решения сложностей, которых было не мало, я заметил, что информации по версии 3.1.0 довольно мало, если не считать документацию. (https://docs.spring.io/spring-security/reference/index.html)

Настройки приложения

Первым делом, начав работу над добавлением авторизации в свое приложение, я добавил соответствующую зависимость в pom.xml

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>

Следующий шагом я приступил к настройке базы данных и подключению PostgreSQL. Я решил использовать application.yml вместо application.properties, так как данный формат является более удобным и читаемым

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/demoproject 
    username: postgres 
    password: password!456 
    driver-class-name: org.postgresql.Driver

SecurityConfig

Основные сложности у меня возникли в конфигурации, поэтому попробую расписать подробнее.

Первым делом я создал объект DataSource, который позволил связать Security с
приложением.

private DataSource dataSource;

@Autowired
public SecurityConfig(DataSource dataSource) { this.dataSource = dataSource; }

Следующим шагом я реализовал метод, создающий сущность JdbcUserDetailsManager. JdbcUserDetailsManager - реализует интерфейс UserDetailsManager, который позволяет работать с пользователями, в том числе создавать их при необходимости. Так как цели реализовывать полноценный механизм регистрации нет, то воспользовался методом createUser().

@Bean
public JdbcUserDetailsManager user(PasswordEncoder encoder) {
    UserDetails admin = User.builder()
            .username("admin")
            .password(encoder.encode("adm_psw"))
            .roles("ADMIN")
            .authorities("ADMIN")
            .build();
    JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager(dataSource);
    jdbcUserDetailsManager.createUser(admin);
    return jdbcUserDetailsManager;
}

Момент создания пользователя можно исключить и реализовать возможность полноценной регистрации или иным образом заполнить базу необходимыми данными - дальнейшую работу с базой я стал вести с Liquibase. Тогда метод будет выглядеть так:

@Bean
public JdbcUserDetailsManager user(PasswordEncoder encoder) {
    JdbcUserDetailsManager jdbcUserDetailsManager = new JdbcUserDetailsManager(dataSource);
    return jdbcUserDetailsManager;
}

В базе так же должны быть таблицы authorities:

create table authorities
(
    username  varchar,
    authority varchar
);

и users:

create table users
(
    username      varchar,
    password      varchar,
    enabled       varchar
    priority      integer
);

Далее логика доступа к необходимым эндпоинтам. Необходимый эндпоинт прописывается в requestMatchers(). С помощью hasAuthority или hasRole позволяем доступ определенной категории пользователей

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
            .authorizeHttpRequests(
                    (authorize) -> authorize
                            .dispatcherTypeMatchers(DispatcherType.FORWARD, DispatcherType.ERROR).permitAll()
                            .requestMatchers("/admin").hasAuthority("ADMIN")
                            .requestMatchers("/user").hasAuthority("USER")
                            .anyRequest().authenticated())
            .httpBasic(Customizer.withDefaults())
            .formLogin(Customizer.withDefaults());
    return http.build();
}

Заключение

На этом в целом все. Далее можно создать тестовый контроллер и проверить работу авторизации в приложении. Как вариант, проверка через постман. Для этого в Authorization выбирает type Basic Auth. В полях username и password прописываем заданные ранее значения.

Подробную информацию о специфике методов и работы с Spring Security все же рекомендую брать из документации.

Код моего проекта можно найти на моем аккаунте в GitHub

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

Комментарии (5)


  1. Dddn
    16.08.2023 12:37

    О, спасибо, как раз искал информацию. Spring Security 3 сильно изменили. Ещё бы примеров про тестирование информации.


  1. xini
    16.08.2023 12:37

    Коллеги, поделитесь опытом, часто ли приходиться самостоятельно настраивать таким образом speing-security? Мне кажется это все ненужным, когда есть OAuth2, OIDC, Keycloak и spring-boot-starter-oauth2-resource-server


    1. Kmplzz
      16.08.2023 12:37

      Keycloak нужно устанавливать и поддерживать, а тут прикрутил basic auth и все работает. Я не говорю, что basic лучше, но на многих проектах присутствует


  1. shamank
    16.08.2023 12:37

    блин, огромное спасибо!!! сам с этим вожусь уже не первый день, нигде не мог найти нормальное разъяснение...


  1. Mrakobec
    16.08.2023 12:37

    К чему эта статья? В дока всё описано, либо достаточно зайти в нужный интерфейс и в нём всё также прекрасно расписано. Основные изменения - это ввод лямбда функций в качестве параметров, вместо огромной колбасы.