JavaRush /Курси /Модуль 5. Spring /Лекція 110: Налаштування Spring Security для мікросервісі...

Лекція 110: Налаштування Spring Security для мікросервісів

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

Мікросервіси, як невеликі самодостатні модулі, взаємодіють один з одним, щоб створювати складні системи. При цьому безпека відіграє ключову роль, бо мікросервіси обмінюються даними, які можуть бути конфіденційними. Без правильної настройки доступу легко допустити витоки, помилки прав доступу і, як наслідок, втрату довіри користувачів.

Для роботи з мікросервісами Spring Security надає гнучкі механізми захисту і управління правами доступу. Давай(те) разом розберемося, як зробити наші мікросервісні системи не лише функціональними, а й безпечними.

Отже, вмикаємо Spring Security і обговорюємо правильні підходи та практики.


Трохи теорії

Для початку коротко розберемо потреби мікросервісів у плані безпеки:

  1. Авторизація та аутентифікація. Потрібно чітко визначити, хто робить запит, і чи має цей "хтось" право на доступ до ресурсу.
  2. Управління ролями та доступами. Наприклад, в нашому додатку адміністратори бачать більше даних, ніж звичайні користувачі.
  3. Міжсервісна взаємодія. Один мікросервіс має бути впевнений, що запит від іншого сервісу дійсно походить від довіреної служби.

У мікросервісній архітектурі часто доводиться розділяти безпеку на два рівні:

  • Зовнішній доступ — запити від клієнта (користувача) до мікросервісів.
  • Внутрішні комунікації — взаємодія між мікросервісами.

Для вирішення задач безпеки ми будемо використовувати комбінацію Spring Security і JWT — ідеальний дует для забезпечення захисту і простоти налаштування.


Практична частина: налаштування безпеки в Spring Security

Крок 1: Підключаємо Spring Security Для початку додамо залежність Spring Security у наш pom.xml:


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

Ця залежність додає в наш додаток все необхідне для базової настройки безпеки.


Крок 2: Створюємо конфігурацію безпеки

Для мікросервісів зазвичай починаємо з Java-based конфігурації. Створимо клас, у якому будемо конфігурувати Spring Security.


import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .csrf().disable() // Вимикаємо CSRF для спрощення (тільки для API!)
            .authorizeRequests()
                .antMatchers("/public/**").permitAll() // Публічний доступ
                .antMatchers("/admin/**").hasRole("ADMIN") // Тільки для ролей ADMIN
                .anyRequest().authenticated() // Усі інші запити мають бути авторизовані
            .and()
            .httpBasic(); // Використовуємо базову аутентифікацію (на початок)
    }
}

Що ми тут зробили:

  1. Вимкнули CSRF (це важливо, бо ми працюємо з REST API). Проте будьте обережні — у продакшні CSRF варто враховувати.
  2. Налаштували публічні та захищені маршрути. Тепер /public/** доступний для всіх, а /admin/** — лише для адміністраторів.

Крок 3: Додаємо користувачів у пам'ять

Зараз додамо просту конфігурацію для збереження користувачів у пам'яті. Це корисно на етапі розробки, щоб швидко налаштувати доступ.


@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.inMemoryAuthentication()
        .withUser("user").password("{noop}password").roles("USER") // {noop} означає, що пароль не зашифрований
        .and()
        .withUser("admin").password("{noop}admin").roles("ADMIN");
}

Тепер у нас є два користувачі: "user" з паролем "password", який належить до ролі USER, і "admin" з паролем "admin", який є ADMIN.

Крок 4: Додаємо JWT

Тепер давайте додамо токенізацію за допомогою JWT. JWT замінить базову аутентифікацію і дозволить нам гнучко керувати доступом.

Крок 4.1: Додаємо JWT-залежності

Оновимо pom.xml, щоб додати бібліотеку для роботи з JWT:


<dependency>
  <groupId>io.jsonwebtoken</groupId>
  <artifactId>jjwt</artifactId>
  <version>0.9.1</version>
</dependency>

Крок 4.2: Створюємо утиліту для роботи з JWT


import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;

import java.util.Date;

public class JwtUtil {
    private static final String SECRET_KEY = "super_secret_key";

    public String generateToken(String username) {
        return Jwts.builder()
                .setSubject(username)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + 1000 * 60 * 60 * 10)) // 10 годин
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY)
                .compact();
    }

    public String validateToken(String token) {
        return Jwts.parser()
                .setSigningKey(SECRET_KEY)
                .parseClaimsJws(token)
                .getBody().getSubject();
    }
}

Крок 4.3: Налаштовуємо фільтр для JWT-аутентифікації


import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class JwtFilter extends OncePerRequestFilter {

    private final JwtUtil jwtUtil;

    public JwtFilter(JwtUtil jwtUtil) {
        this.jwtUtil = jwtUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) {
        String authHeader = request.getHeader("Authorization");

        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            String token = authHeader.substring(7);
            String username = jwtUtil.validateToken(token);

            if (username != null) {
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(request, response);
    }
}

Підсумки

Тепер наш додаток готовий працювати з JWT для аутентифікації і захисту мікросервісів. Можете протестувати API за допомогою інструментів на кшталт Postman або curl, передаючи JWT з запитами. Прощавай, SQL-ін'єкції в заголовках запитів! Spring Security тут, щоб усе захистити.

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