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

Лекция 109: Защита ресурсов с использованием OAuth2

Модуль 5. Spring
11 уровень , 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 контроллер, который демонстрирует использование ролей и областей.


@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: убедитесь, что доступ предоставляется или отклоняется в зависимости от роли и области.

Управление ролями и правами

Роли в 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.

Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ