JavaRush /Курси /Модуль 5. Spring /Лекція 109: Захист ресурсів з використанням OAuth2

Лекція 109: Захист ресурсів з використанням OAuth2

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

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

Без адекватного рівня захисту будь-хто з базовим ПО (так, ми дивимось у бік Postman) зможе отримати доступ до API, а ми цього точно допускати не хочемо.

OAuth2 дає відмінний інструмент для керування доступом: токени. І сьогодні розберемося, як налаштувати ваш Spring Boot проєкт, щоб забезпечити строгий захист на рівні ресурсів.


Компоненти захисту ресурсів

Перш ніж занурюватись у практику, давайте коротко визначимо ключові компоненти, які потрібні для захисту ресурсів з OAuth2:

  1. Ресурсний сервер (Resource Server):
    • Компонент, який обслуговує захищені дані та перевіряє токени перед наданням доступу. Тут зазвичай розгортаються ваші REST API.
  2. Токен доступу (Access Token):
    • Спеціальний токен, з яким клієнт може стукати у двері до ресурсного сервера. Токен несе в собі інформацію, наприклад, які дії дозволені і для якого користувача.
  3. Ролі та права доступу:
    • Керування доступом через ролі (наприклад, ROLE_USER, ROLE_ADMIN) і області (scopes), які визначають функціональні можливості користувача.
  4. Spring Security:
    • Фреймворк, який дозволяє організувати перевірку прав доступу до ресурсів, перевірку токенів і налаштування політик безпеки.

Реалізація захисту ресурсів у Spring Boot

Переходимо до практики. Налаштовуватимемо Spring Boot додаток у ролі ресурсного сервера, використовуючи OAuth2 і JWT.

Підготовка проєкту

Переконайтеся, що в вас є наступний набір залежностей у pom.xml (або build.gradle):


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

Ці залежності додають підтримку ресурсного сервера і Spring Security.


Налаштування ресурсного сервера

1. Конфігурація security-фільтрів

Створіть клас конфігурації для Spring Security:


@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
                .antMatchers("/public/**").permitAll() // Відкриті ресурси
                .antMatchers("/admin/**").hasRole("ADMIN") // Тільки для адмінів
                .antMatchers("/user/**").hasRole("USER") // Тільки для користувачів
                .anyRequest().authenticated() // Усі інші вимагають аутентифікації
            .and()
            .oauth2ResourceServer()
                .jwt(); // Використовуємо JWT для перевірки токена
    }
}

Тут ми визначаємо:

  • Які ендпоінти є публічними.
  • Які ресурси вимагають певних ролей.
  • Налаштовуємо OAuth2 ресурсний сервер з використанням JWT.

2. Конфігурація токенів JWT

Додайте в application.yml (або application.properties) параметри, щоб вказати, де шукати публічний ключ для перевірки підпису токенів JWT:


spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://auth-server.example.com/realms/myrealm
# Тут має бути URL вашого сервера авторизації (Issuer URI)

Параметр issuer-uri каже Spring Security, де знаходиться сервер авторизації (наприклад, Keycloak або Auth0), щоб витягти інформацію про конфігурацію токенів.


Приклад захищеного контролера

Давайте створимо REST контролер, який демонструє використання ролей і областей (scopes).


@RestController
@RequestMapping("/api")
public class ResourceController {

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

    @GetMapping("/user/hello")
    public String userEndpoint(@AuthenticationPrincipal Jwt jwt) {
        return "Привіт, користувачу " + jwt.getClaimAsString("preferred_username") + "!";
    }

    @GetMapping("/admin/dashboard")
    public String adminEndpoint() {
        return "Це адміністративний ресурс. Ласкаво просимо, великий Адмін!";
    }
}
  • Ендпоінт /public доступний усім.
  • Ендпоінт /user/hello вимагає наявності ролі USER і виводить інформацію з токена JWT (наприклад, preferred_username).
  • Ендпоінт /admin/dashboard доступний тільки адміністраторам.

Як перевірити роботу сервера?

  • Крок 1: отримайте JWT токен. Зробіть це через сервер авторизації (наприклад, Keycloak або Auth0).
  • Крок 2: надішліть запит з заголовком Authorization: Bearer <ваш токен> до захищених ендпоінтів.
  • Крок 3: переконайтеся, що доступ надається або відхиляється в залежності від ролі та областей (scopes).

Керування ролями та правами

Ролі в OAuth2 і JWT відіграють ключову роль у наданні доступу до ресурсів. Наприклад, роль ROLE_ADMIN дає доступ до адміністративних ресурсів, а ROLE_USER — до користувацьких.

Токен JWT може включати області (scopes) і ролі як додаткові claims. Приклад структури токена:


{
  "sub": "user123",
  "scope": "read write",
  "roles": ["USER", "ADMIN"],
  "exp": 1698777600
}

Як перевіряти ролі в Spring? Spring Security автоматично перетворює roles у токені в авторизацію. Ви можете використовувати анотації:

@PreAuthorize("hasRole('ADMIN')")
@GetMapping("/secure/admin")
public String securedAdminEndpoint() {
    return "Тільки для адмінів!";
}

Типові помилки й їх виправлення

  1. Помилка "403 Forbidden" при доступі з валідним токеном — швидше за все, у вас неправильно налаштовані ролі або області. Переконайтеся, що ролі, вказані в токені, відповідають очікуваним.
  2. Помилка перевірки підпису JWT — зазвичай це означає, що ваш ресурсний сервер не зміг отримати публічний ключ від сервера авторизації. Перевірте параметр issuer-uri і переконайтеся, що сервер авторизації доступний.
  3. Термін дії токена минув — переконайтеся, що ваші клієнти використовують Refresh токени для оновлення токенів доступу.

Застосування в реальному житті

Використання OAuth2 і JWT для захисту ресурсів забезпечує надійну і масштабовану безпеку для мікросервісних архітектур. Цей підхід використовується в багатьох реальних проєктах, починаючи від корпоративних додатків до платформ соціальної аутентифікації.

Наступного разу, коли зайдете на сайт і побачите кнопку "Увійти через Google", ви вже знаєте, що там працює OAuth2.

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