JavaRush /Курси /Модуль 5. Spring /Практика: налаштування базової безпеки у веб-застосунку

Практика: налаштування базової безпеки у веб-застосунку

Модуль 5. Spring
Рівень 17 , Лекція 5
Відкрита

Сьогодні переходимо до практики — створимо базовий веб-застосунок з налаштуванням Spring Security для захисту маршрутів і реалізації аутентифікації користувачів. Готуйтеся до бою, друзі!


Від побудови застосунку до додавання безпеки

Мета та структура задачі

Перш ніж писати код, давайте уявимо, що ми створюємо не просто застосунок, а цифровий ресторан. Потрібно зрозуміти, хто прийшов у гості (аутентифікація) і куди їх можна пустити (авторизація). У звичайному ресторані є фейс-контроль і VIP-зони, а в нашому застосунку буде Spring Security.

Ось наш план дій:

  1. Створимо мінімальний Spring Boot застосунок — наш "ресторан"
  2. Додамо базовий захист за допомогою Spring Security — встановимо "двері й замки"
  3. Налаштуємо систему перевірки відвідувачів — хто ви і чи можна вам довіряти?
  4. Визначимо правила доступу до різних зон — хто куди може ходити
  5. Перевіримо нашу систему безпеки через браузер або Postman — влаштуємо тестовий "візит"

Готові побудувати найбезпечніший цифровий ресторан? Поїхали!

Крок 1: Створюємо мінімалістичний Spring Boot застосунок

Спочатку створимо новий проект Spring Boot. Вибираємо залежності:

  • Spring Web — щоб наш застосунок міг обробляти HTTP-запити.
  • Spring Security — власне, для налаштування безпеки.

Не забудьте додати Gradle або Maven в ваш проєкт. Наприклад, для Maven ваш pom.xml виглядатиме так:


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

Тепер додамо простий контролер.


@RestController
public class GreetingController {

    @GetMapping("/public")
    public String publicEndpoint() {
        return "Цей ендпоінт доступний усім!";
    }

    @GetMapping("/secure")
    public String secureEndpoint() {
        return "Ви зайшли у захищену зону!";
    }
}

Запустіть застосунок і спробуйте відкрити маршрути /public і /secure. Зверніть увагу, що Spring Security уже захищає весь ваш API. Спробуйте дістатися до /secure, і ви побачите вікно логіну в браузері. Це базовий захист, який надає Spring Security "з коробки".

Крок 2: Налаштовуємо базову конфігурацію

Тепер створимо кастомну конфігурацію безпеки. Нам потрібно зробити так, щоб:

  1. /public залишався відкритим для всіх.
  2. /secure був захищений і доступний тільки аутентифікованим користувачам.

Створимо конфігураційний клас.


@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public").permitAll() // Доступ відкритий для всіх
                .anyRequest().authenticated()      // Усі інші запити потребують аутентифікації
                .and()
            .formLogin()                           // Вмикаємо стандартну форму логіну
                .and()
            .httpBasic();                          // Вмикаємо HTTP Basic авторизацію
    }
}

Запустіть застосунок заново. Тепер /public відкривається без проблем, а доступ до /secure вимагає введення імені користувача та пароля через стандартну форму логіну.

Крок 3: Налаштування користувачів

За замовчуванням Spring Security використовує передвстановленого користувача з ім'ям user і випадковим паролем, який відображається в логах застосунку при запуску. Якщо вам набридло бігати очима по логам у пошуках пароля, давайте додамо власних користувачів в application.properties.


spring.security.user.name=admin
spring.security.user.password=admin123

Тепер користувач admin зможе аутентифікуватися з паролем admin123.

Але що робити, якщо потрібно додати різні ролі (наприклад, адміністраторів і звичайних користувачів)? Трохи піднастроїмо систему.

Крок 4: Додаємо авторизацію на основі ролей

Ми додамо дві ролі: ROLE_ADMIN і ROLE_USER. Для цього спочатку оновимо нашу конфігурацію безпеки:


@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        .authorizeRequests()
            .antMatchers("/public").permitAll()
            .antMatchers("/secure").hasRole("ADMIN") // Доступ до /secure тільки для адмінів
            .anyRequest().authenticated()
            .and()
        .formLogin()
            .and()
        .httpBasic();
}

Тепер створимо користувачів з різними ролями. Для цього перевизначимо метод configure у нашому класі SecurityConfig:


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .withUser("admin").password(passwordEncoder().encode("admin123")).roles("ADMIN") // Адмін
        .and()
        .withUser("user").password(passwordEncoder().encode("user123")).roles("USER");   // Звичайний користувач
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

Тепер у нас два користувачі:

  • admin з паролем admin123 і роллю ROLE_ADMIN.
  • user з паролем user123 і роллю ROLE_USER.

І тільки адміністратор (admin) зможе отримати доступ до /secure.

Крок 5: Тестуємо безпеку

Запустіть застосунок і протестуйте його:

  1. Відкрийте /public — доступ відкритий для всіх.
  2. Відкрийте /secure — система запросить логін і пароль.
    • Введіть user / user123 — отримаєте відмову в доступі.
    • Введіть admin / admin123 — отримаєте доступ.

Для тестування також можна використовувати Postman. Наприклад, запит до /secure можна відправити з Basic Auth, вказавши ім'я користувача і пароль.

Крок 6: Перевіряємо файл application.properties

Ось що можна додати в application.properties для зручності:


# Логування для налагодження
logging.level.org.springframework.security=DEBUG

Так ви зможете бачити більше інформації про те, як Spring Security обробляє ваші запити.


Часті помилки

  • Помилка: доступ до захищених маршрутів надається будь-якому користувачу. Зазвичай це трапляється через неправильно налаштовані правила у authorizeRequests. Перевірте порядок викликів antMatchers — вони обробляються зверху вниз.
  • IllegalArgumentException: There is no PasswordEncoder mapped for ID "null". Це трапляється, якщо ви забули налаштувати PasswordEncoder. Не забудьте додати бин BCryptPasswordEncoder у ваш код, щоб шифрувати паролі.

Наступний крок — впровадження збереження користувачів і ролей у базі даних, що ми розглянемо в наступних лекціях. Куди ж без інтеграції з реальною базою, правда?

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ