Pytania na rozmowe - Backend Developer

Kompletny przewodnik z odpowiedziami

Java / Podstawy programowania

🎬 Materiały wideo (PL):

1. Czym rozni sie == od equals() w Javie?

🎯 Podstawy:
String a = new String("test");
String b = new String("test");

a == b;       // false - rozne obiekty w pamieci
a.equals(b);  // true - ta sama zawartosc

2. Wyjasnij roznice miedzy ArrayList a LinkedList

🎯 Podstawy:
Cecha ArrayList LinkedList
Struktura Tablica dynamiczna Lista dwukierunkowa
Dostep po indeksie O(1) O(n)
Dodawanie/usuwanie na koncu O(1) amortyzowane O(1)
Dodawanie/usuwanie w srodku O(n) O(1) jesli mamy referencje
Pamiec Mniejsza Wieksza (przechowuje wskazniki)
Kiedy uzywac:
ArrayList - czesty dostep po indeksie, iteracja
LinkedList - czeste dodawanie/usuwanie elementow, implementacja kolejki/stosu

3. Co to jest garbage collector i jak dziala?

🎯 Podstawy:

Garbage Collector (GC) - automatyczny mechanizm zarzadzania pamiecia, ktory usuwa nieuzywane obiekty.

Jak dziala:

  1. Mark - oznacza obiekty osiagalne z "root" (zmienne lokalne, statyczne, watki)
  2. Sweep - usuwa nieoznaczone obiekty
  3. Compact (opcjonalnie) - defragmentuje pamiec

Generacje pamieci:

Popularne algorytmy GC: G1 (domyslny od Java 9), ZGC, Shenandoah

4. Czym sa typy generyczne (generics) i dlaczego sa wazne?

🎯 Podstawy:

Generics pozwalaja parametryzowac typy, zapewniajac bezpieczenstwo typow w czasie kompilacji.

// Bez generics - mozliwy ClassCastException w runtime
List list = new ArrayList();
list.add("tekst");
Integer num = (Integer) list.get(0); // blad w runtime!

// Z generics - blad wykryty w czasie kompilacji
List<String> list = new ArrayList<>();
list.add("tekst");
list.add(123); // blad kompilacji!
Zalety: Bezpieczenstwo typow w compile-time, brak potrzeby rzutowania, czytelniejszy kod

5. Wyjasnij roznice miedzy final, finally i finalize

🎯 Podstawy:
Slowo kluczowe Zastosowanie
final Modyfikator: klasa nie moze byc dziedziczona, metoda nie moze byc nadpisana, zmienna nie moze byc zmieniona
finally Blok kodu wykonywany zawsze po try/catch (do sprzatania zasobow)
finalize Metoda wywolywana przez GC przed usunieciem obiektu (deprecated od Java 9)
final int MAX = 100;  // stala

try {
    // kod
} catch (Exception e) {
    // obsluga bledu
} finally {
    // zawsze sie wykona - zamkniecie zasobow
}

6. Co to jest immutability i dlaczego jest wazna?

🎯 Podstawy:

Obiekt niemutowalny - po utworzeniu jego stan nie moze byc zmieniony.

// String jest immutable
String s = "hello";
s.toUpperCase(); // nie zmienia s, zwraca nowy obiekt

// Tworzenie immutable klasy
public final class Person {
    private final String name;

    public Person(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
    // brak setterow!
}
Zalety: Thread-safety (mozna bezpiecznie wspoldzielic miedzy watkami), przewidywalnosc, bezpieczne jako klucze w HashMap, latwiejsze debugowanie

7. Czym różni się interfejs od klasy abstrakcyjnej?

🎯 Podstawy:
Cecha Interfejs Klasa abstrakcyjna
Definicja Typ referencyjny definiujący kontrakt Niekompletna klasa bazowa do rozszerzenia
Dziedziczenie Klasa może implementować wiele interfejsów Klasa może rozszerzyć tylko jedną klasę
Relacja „Może zachowywać się jak” (capability) „Jest typem” (is-a)
Pola Tylko public static final (stałe) Dowolne: private, protected, final, mutable
Konstruktor Brak – nie można przekazać zależności przez konstruktor Tak – można inicjalizować pola wspólne i wymuszać zależności
Metody Abstrakcyjne, default, static, private (od Java 9) Abstrakcyjne i konkretne
Stan obiektu Nie przechowuje stanu instancji Może przechowywać stan instancji (pola)
Widoczność metod Metody public (domyślnie) Dowolna: private / protected / public
Zastosowanie Definicja kontraktu API, wiele implementacji, luźne sprzężenie Wspólna implementacja, szkielet algorytmu, kontrola przepływu, częściowa implementacja

Przykłady zastosowania klas abstrakcyjnych

Przykłady zastosowania interfejsów

Podsumowanie wyboru

8. Wyjasnij mechanizm Stream API i podaj przyklady uzycia

🎯 Podstawy:

Stream API (od Java 8) - deklaratywne przetwarzanie kolekcji.

List<String> names = List.of("Anna", "Jan", "Adam", "Ewa");

// Filtrowanie i mapowanie
List<String> result = names.stream()
    .filter(name -> name.startsWith("A"))
    .map(String::toUpperCase)
    .sorted()
    .collect(Collectors.toList());
// ["ADAM", "ANNA"]

// Redukcja
int sum = List.of(1, 2, 3, 4, 5).stream()
    .reduce(0, Integer::sum); // 15

// Grupowanie
Map<Integer, List<String>> byLength = names.stream()
    .collect(Collectors.groupingBy(String::length));

Operacje:

9. Co to jest Optional i jak pomaga unikac NullPointerException?

🎯 Podstawy:

Optional - kontener, ktory moze zawierac wartosc lub byc pusty.

// Zamiast zwracac null
public Optional<User> findById(Long id) {
    User user = repository.find(id);
    return Optional.ofNullable(user);
}

// Uzycie
Optional<User> userOpt = findById(1L);

// Bezpieczne pobieranie
String name = userOpt
    .map(User::getName)
    .orElse("Unknown");

// Rzucenie wyjatku jesli brak
User user = userOpt
    .orElseThrow(() -> new NotFoundException("User not found"));

// Wykonanie akcji jesli istnieje
userOpt.ifPresent(u -> System.out.println(u.getName()));
Nie uzywaj Optional: Jako pola klasy, jako parametru metody, w kolekcjach

Spring Framework / Spring Boot

🎬 Materiały wideo (PL):

10. Czym jest Dependency Injection i jakie sa jego rodzaje?

🎯 Podstawy:

Dependency Injection (DI) - wzorzec, w ktorym zaleznosci sa dostarczane z zewnatrz, zamiast byc tworzone wewnatrz klasy.

// 1. Constructor Injection (ZALECANY)
@Service
public class OrderService {
    private final ProductRepository repository;

    public OrderService(ProductRepository repository) {
        this.repository = repository;
    }
}

// 2. Setter Injection
@Service
public class OrderService {
    private ProductRepository repository;

    @Autowired
    public void setRepository(ProductRepository repository) {
        this.repository = repository;
    }
}

// 3. Field Injection (NIEZALECANY)
@Service
public class OrderService {
    @Autowired
    private ProductRepository repository;
}
Dlaczego Constructor Injection jest najlepszy: Wymusza podanie wszystkich zaleznosci, umozliwia pola final (immutability), latwiejsze testowanie (bez refleksji)

11. Roznice miedzy @Component, @Service, @Repository i @Controller

🎯 Podstawy:

Wszystkie sa specjalizacjami @Component i oznaczaja bean zarzadzany przez Springa.

Adnotacja Warstwa Dodatkowe funkcje
@Component Ogolna Bazowa adnotacja
@Service Logika biznesowa Semantyczna, brak dodatkowych funkcji
@Repository Dostep do danych Automatyczna translacja wyjatkow SQL na DataAccessException
@Controller Web (MVC) Obsluguje zadania HTTP, zwraca widoki
@RestController Web (REST) = @Controller + @ResponseBody

12. Jak dziala Spring Security? Co to jest SecurityFilterChain?

🎯 Podstawy:

Spring Security dziala jako lancuch filtrow przechwytujacych zadania HTTP.

Request -> DelegatingFilterProxy -> FilterChainProxy -> [Security Filters] -> Controller

Glowne filtry:

  1. SecurityContextPersistenceFilter - laduje kontekst bezpieczenstwa
  2. UsernamePasswordAuthenticationFilter - obsluguje login
  3. BasicAuthenticationFilter - HTTP Basic Auth
  4. BearerTokenAuthenticationFilter - JWT
  5. ExceptionTranslationFilter - obsluga wyjatkow
  6. AuthorizationFilter - sprawdzanie uprawnien
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(csrf -> csrf.disable())
            .sessionManagement(session ->
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2.jwt(Customizer.withDefaults()))
            .build();
    }
}

13. Czym rozni sie @RestController od @Controller?

🎯 Podstawy:
// @Controller - zwraca nazwy widokow (MVC)
@Controller
public class WebController {

    @GetMapping("/home")
    public String home(Model model) {
        model.addAttribute("message", "Hello");
        return "home"; // szuka templates/home.html
    }

    @GetMapping("/api/data")
    @ResponseBody // potrzebne do zwrocenia JSON
    public Data getData() {
        return new Data();
    }
}

// @RestController = @Controller + @ResponseBody na kazdej metodzie
@RestController
public class ApiController {

    @GetMapping("/api/data")
    public Data getData() {
        return new Data(); // automatycznie serializowane do JSON
    }
}

14. Wyjasnij cykl zycia beana w Springu

🎯 Podstawy:
1. Instantiation (tworzenie obiektu) | 2. Populate Properties (wstrzykiwanie zaleznosci) | 3. BeanNameAware.setBeanName() | 4. BeanFactoryAware.setBeanFactory() | 5. ApplicationContextAware.setApplicationContext() | 6. BeanPostProcessor.postProcessBeforeInitialization() | 7. @PostConstruct / InitializingBean.afterPropertiesSet() | 8. BeanPostProcessor.postProcessAfterInitialization() | === Bean gotowy do uzycia === | 9. @PreDestroy / DisposableBean.destroy()
@Component
public class MyBean {

    @PostConstruct
    public void init() {
        // wykonywane po utworzeniu beana i wstrzyknieciu zaleznosci
    }

    @PreDestroy
    public void cleanup() {
        // wykonywane przed zniszczeniem beana
    }
}

15. Co to jest @Transactional i jak dziala propagacja transakcji?

🎯 Podstawy:

@Transactional - zarzadza transakcjami deklaratywnie (przez AOP proxy).

@Service
public class OrderService {

    @Transactional
    public void createOrder(Order order) {
        // wszystko w jednej transakcji
        orderRepository.save(order);
        inventoryService.decreaseStock(order.getItems());
        // jesli wystapi wyjatek - rollback calosci
    }
}
Propagation Opis
REQUIRED (domyslny) Uzywa istniejacej lub tworzy nowa
REQUIRES_NEW Zawsze tworzy nowa (zawieszajac obecna)
NESTED Tworzy zagniezzona transakcje (savepoint)
SUPPORTS Uzywa istniejacej lub dziala bez transakcji
NOT_SUPPORTED Zawiesza istniejaca, dziala bez transakcji
MANDATORY Wymaga istniejacej transakcji
NEVER Rzuca wyjatek jesli istnieje transakcja
Wazne: @Transactional nie dziala przy wywolaniu metody z tej samej klasy (self-invocation) - proxy nie przechwytuje.

15a. Inne wlasciwosci adnotacji @Transactional

Oprocz propagacji i poziomu izolacji, @Transactional posiada kilka niezaleznych wlasciwosci, ktore wplywaja na zachowanie transakcji.

Wlasciwosc Opis Przyklad / Uwagi
readOnly Oznacza transakcje jako tylko-do-odczytu. Moze pozwolic ORM i bazie na optymalizacje. @Transactional(readOnly = true)
Nie blokuje zapisu technicznie, ale zapis jest bledem logicznym.
timeout Maksymalny czas trwania transakcji (w sekundach). Po przekroczeniu nastepuje rollback. @Transactional(timeout = 5)
Chroni przed "wiszacymi" transakcjami.
rollbackFor Okresla, dla jakich wyjatkow ma nastapic rollback. Domyslnie rollback jest tylko dla RuntimeException.
@Transactional(rollbackFor = Exception.class)
noRollbackFor Wyjatki, dla ktorych rollback nie powinien nastapic. @Transactional(noRollbackFor = BusinessException.class)
isolation Poziom izolacji transakcji (ACID). READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE
Chroni przed dirty read, non-repeatable read itd.
transactionManager Wskazuje konkretny menedzer transakcji. Wazne przy wielu zrodlach danych
@Transactional(transactionManager = "orderTxManager")
Wazne:

16. Jak skonfigurowalbys polaczenie z baza danych w Spring Boot?

🎯 Podstawy:
# application.yml
spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/mydb
    username: ${DB_USERNAME:admin}
    password: ${DB_PASSWORD:secret}
    driver-class-name: org.postgresql.Driver
    hikari:
      maximum-pool-size: 10
      minimum-idle: 5
      idle-timeout: 300000

  jpa:
    hibernate:
      ddl-auto: validate  # none, validate, update, create, create-drop
    show-sql: false
    properties:
      hibernate:
        format_sql: true
        dialect: org.hibernate.dialect.PostgreSQLDialect

16b. Kluczowe elementy JPA (Java Persistence API)

JPA to specyfikacja Javy do mapowania obiektowo-relacyjnego (ORM). Hibernate jest jej najpopularniejszą implementacją.

Entity

Reprezentuje tabelę w bazie danych. Każda instancja to jeden wiersz.

@Entity
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}

EntityManager

Główny interfejs do operacji na encjach (zarządza cyklem życia obiektów):

entityManager.persist(user);     // INSERT - zapisuje nowy obiekt
entityManager.merge(user);       // UPDATE - aktualizuje odłączony obiekt
entityManager.remove(user);      // DELETE - usuwa obiekt
entityManager.find(User.class, id); // SELECT - znajduje po kluczu głównym

Stany encji (Persistence Context)

Stan Opis
New/Transient Obiekt utworzony, ale nie zarządzany przez JPA
Managed Po persist() lub find() — zmiany automatycznie synchronizowane z bazą (dirty checking)
Detached Po zamknięciu EntityManager — obiekt odłączony, zmiany nie są śledzone
Removed Po remove() — zaplanowany do usunięcia

Co robi Hibernate pod spodem

Hibernate jako implementacja JPA:

JPA vs Hibernate vs Spring Data JPA:
JPA — specyfikacja (interfejs)
Hibernate — implementacja JPA (wykonuje rzeczywistą pracę)
Spring Data JPA — dodatkowa warstwa abstrakcji nad JPA (generuje implementację z nazw metod w Repository)

Bazy danych / SQL

🎬 Materiały wideo (PL):

17. Czym rozni sie INNER JOIN od LEFT JOIN?

🎯 Podstawy:
SQL JOINS - wizualizacja wszystkich typów joinów
-- INNER JOIN - tylko pasujace rekordy z obu tabel
SELECT c.name, o.amount
FROM customers c
INNER JOIN orders o ON c.id = o.customer_id;
-- Zwraca tylko klientow, ktorzy maja zamowienia

-- LEFT JOIN - wszystkie z lewej + pasujace z prawej
SELECT c.name, o.amount
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id;
-- Zwraca WSZYSTKICH klientow, nawet bez zamowien (amount = NULL)
Typ JOIN Opis Kiedy używać
INNER JOIN Tylko rekordy pasujące w obu tabelach Gdy potrzebujesz tylko kompletnych danych
LEFT JOIN Wszystkie z lewej + pasujące z prawej (NULL jeśli brak) Gdy chcesz wszystkich z głównej tabeli
RIGHT JOIN Wszystkie z prawej + pasujące z lewej Rzadko używany (zamień tabele i użyj LEFT)
FULL OUTER JOIN Wszystkie z obu tabel (NULL gdzie brak dopasowania) Gdy potrzebujesz kompletnego obrazu obu tabel

18. Co to sa indeksy i kiedy warto je stosowac?

🎯 Podstawy:

Indeks - struktura danych przyspieszajaca wyszukiwanie (najczesciej B-tree).

-- Tworzenie indeksu
CREATE INDEX idx_customer_email ON customers(email);

-- Indeks zlozony
CREATE INDEX idx_order_customer_date ON orders(customer_id, created_at);

-- Indeks unikalny
CREATE UNIQUE INDEX idx_user_username ON users(username);
Kiedy stosowac: Kolumny czesto uzywane w WHERE, JOIN, ORDER BY; kolumny z duza selektywnoscia; klucze obce
Kiedy NIE stosowac: Male tabele; kolumny rzadko uzywane w zapytaniach; kolumny czesto aktualizowane; kolumny z mala selektywnoscia (np. boolean)

19. Wyjasnij wlasciwosci ACID

🎯 Podstawy:
Wlasciwosc Opis Przyklad
Atomicity (Atomowosc) Transakcja wykonuje sie w calosci lub wcale Przelew: obie operacje (debit i credit) musza sie udac
Consistency (Spojnosc) Baza zawsze przechodzi z jednego spojnego stanu do drugiego Suma sald przed i po przelewie jest taka sama
Isolation (Izolacja) Rownolegle transakcje nie wplywaja na siebie Dwa przelewy z tego samego konta nie powoduja race condition
Durability (Trwalosc) Zatwierdzone zmiany sa trwale (nawet po awarii) Po COMMIT dane sa bezpieczne na dysku

20. Czym rozni sie baza SQL od NoSQL?

🎯 Podstawy:
Cecha SQL NoSQL
Schemat Staly, zdefiniowany Elastyczny/brak
Struktura Tabele z relacjami Dokumenty, klucz-wartosc, grafy
Skalowanie Wertykalne (mocniejszy serwer) Horyzontalne (wiecej serwerow)
ACID Pelne wsparcie Czesto eventual consistency
Zapytania SQL - potezny jezyk zapytan Ograniczone, zalezne od typu
Kiedy SQL: Dane relacyjne z powiazaniami, potrzeba transakcji ACID, zlozone zapytania analityczne
Kiedy NoSQL: MongoDB (elastyczna struktura), Redis (cache), Cassandra (duze dane rozproszone), Neo4j (grafy)

21. Co to jest N+1 problem i jak go rozwiazac?

🎯 Podstawy:

Problem N+1 - wykonanie 1 zapytania po liste + N zapytan po powiazane dane.

// Problem: 1 zapytanie po zamowienia + N zapytan po klientow
List<Order> orders = orderRepository.findAll();
for (Order order : orders) {
    System.out.println(order.getCustomer().getName()); // kazde wywolanie = nowe zapytanie!
}

Rozwiazania:

// 1. JOIN FETCH (JPQL)
@Query("SELECT o FROM Order o JOIN FETCH o.customer")
List<Order> findAllWithCustomers();

// 2. @EntityGraph
@EntityGraph(attributePaths = {"customer"})
List<Order> findAll();

// 3. @BatchSize (Hibernate)
@ManyToOne
@BatchSize(size = 25) // laduje klientow partiami po 25
private Customer customer;

22. Wyjasnij poziomy izolacji transakcji

🎯 Podstawy:
Poziom Dirty Read Non-repeatable Read Phantom Read
READ_UNCOMMITTED mozliwe mozliwe mozliwe
READ_COMMITTED - mozliwe mozliwe
REPEATABLE_READ - - mozliwe
SERIALIZABLE - - -

Problemy:

22a. Jak faktycznie dzialaja poziomy izolacji? (co blokuje baze i co widzi transakcja)

Poziomy izolacji okreslaja jak bardzo transakcje sa od siebie odseparowane oraz jakie mechanizmy kontroli wspolbieznosci stosuje baza (MVCC, locki, snapshoty).

W PostgreSQL (i wiekszosci nowoczesnych baz) dominuje MVCC – Multi Version Concurrency Control, czyli baza nie blokuje odczytow, tylko przechowuje wiele wersji wierszy.


READ UNCOMMITTED

W teorii: mozna czytac dane jeszcze przed COMMIT-em.

W praktyce (PostgreSQL): ten poziom NIE istnieje – jest mapowany do READ COMMITTED, poniewaz Postgres nigdy nie pozwala na dirty read.

Co widzi transakcja?
Kazdy SELECT widzi tylko dane zatwierdzone przed rozpoczeciem zapytania.

Problem:
Dwa SELECT-y w tej samej transakcji moga zwrocic inne wyniki.

Kiedy uzywac?
W praktyce – nigdy jako swiadomy wybor.


READ COMMITTED (domyslny w PostgreSQL)

Jak to dziala?

Ale!
Jesli inna transakcja zrobi COMMIT pomiedzy Twoimi SELECT-ami — kolejny SELECT zobaczy nowe dane.

Co NIE jest blokowane?

Zalety:

Wady:

Typowe zastosowania:

Senior tip:
~90% aplikacji produkcyjnych dziala na READ COMMITTED.


REPEATABLE READ

Kluczowa roznica:
Snapshot tworzony jest raz – na poczatku transakcji.

Oznacza to:

Co blokuje baza?
Nie blokuje odczytow – nadal korzysta z MVCC.
Ale przy zapisie moze dojsc do:

Baza wtedy zabija jedna z transakcji.

Bardzo wazne:
W PostgreSQL phantom read praktycznie nie wystepuje na tym poziomie, poniewaz snapshot jest stabilny.

Kiedy uzywac?

Minus:
wieksze ryzyko rollbackow przy duzej konkurencji.


SERIALIZABLE (najwyzszy poziom)

Cel:
Zachowanie jakby transakcje wykonywaly sie jedna po drugiej.

Jak robi to Postgres?
Nie przez ciezkie locki — tylko przez wykrywanie konfliktow (SSI – Serializable Snapshot Isolation).

Jesli baza wykryje niebezpieczna zaleznosc:

ERROR: could not serialize access due to read/write dependencies

Jedna transakcja musi zostac powtorzona.

Zalety:

Wady:

Kiedy uzywac?


Jak to zapamietac (intuicyjnie)?


Bardzo wazne pytanie rekrutacyjne

Czy wyzszy poziom izolacji zawsze jest lepszy?
👉 Nie.

To zawsze trade-off:

Dlatego:
Najpierw wybieramy mozliwie najnizszy poziom, ktory nadal gwarantuje poprawna logike biznesowa.

22b. Co to jest MVCC (Multi-Version Concurrency Control)?

MVCC (Multi-Version Concurrency Control) - mechanizm umozliwiajacy wspolbiezny dostep do bazy danych poprzez przechowywanie wielu wersji danych. Transakcje dzialaja na podstawie migawki (snapshot) bazy danych.

Jak dziala MVCC (PostgreSQL):

Kazdy wiersz ma ukryte kolumny: ┌────────┬────────┬──────┬──────┐ │ id │ status │ xmin │ xmax │ ├────────┼────────┼──────┼──────┤ │ 1 │ NEW │ 10 │ NULL │ ← utworzony przez transakcje 10 └────────┴────────┴──────┴──────┘ xmin = ID transakcji, ktora UTWORZYLA wiersz xmax = ID transakcji, ktora USUNELA/ZAKTUALIZOWALA wiersz (NULL = aktywny)

Przyklad - UPDATE w MVCC:

-- Stan poczatkowy (transakcja 10 utworzyla wiersz)
-- id=1 | status=NEW | xmin=10 | xmax=NULL

-- Transakcja 20 wykonuje UPDATE:
UPDATE orders SET status = 'PAID' WHERE id = 1;

-- MVCC tworzy NOWA wersje wiersza (nie nadpisuje starej!):
-- id=1 | status=NEW  | xmin=10 | xmax=20   ← stara wersja (oznaczona jako usunieta przez tx 20)
-- id=1 | status=PAID | xmin=20 | xmax=NULL ← nowa wersja (utworzona przez tx 20)

-- Transakcja 15 (rozpoczeta PRZED tx 20) nadal widzi:
-- id=1 | status=NEW  (bo xmin=10 < 15, xmax=20 > 15)

-- Transakcja 25 (rozpoczeta PO tx 20) widzi:
-- id=1 | status=PAID (bo xmin=20 < 25, xmax=NULL)

Zalety MVCC:

Zaleta Opis
Readers nie blokuja Writers SELECT nie blokuje UPDATE/DELETE - kazdy czyta swoja wersje
Writers nie blokuja Readers UPDATE nie blokuje SELECT - stara wersja nadal dostepna
Spojny snapshot Transakcja widzi stabilny obraz danych z momentu rozpoczecia
Mniej deadlockow Minimalizuje blokady = mniejsze ryzyko zakleszczen
Lepsza wydajnosc odczytu Odczyty nie musza czekac na zakonczenie zapisow

MVCC vs tradycyjne blokowanie:

Cecha Tradycyjne blokowanie MVCC
SELECT podczas UPDATE Czeka na zwolnienie blokady Czyta stara wersje natychmiast
Zuzycie pamieci Niskie Wyzsze (przechowuje wiele wersji)
Wymaga czyszczenia Nie Tak (VACUUM w PostgreSQL)
Bazy danych Starsze systemy PostgreSQL, MySQL InnoDB, Oracle
-- PostgreSQL: Reczne czyszczenie starych wersji
VACUUM orders;

-- Automatyczne czyszczenie (domyslnie wlaczone)
-- autovacuum dziala w tle

REST API / Architektura

🎬 Materiały wideo (PL):

23. Jakie sa glowne metody HTTP i do czego sluza?

🎯 Podstawy:

Metody HTTP - opisy i typowe odpowiedzi:

Metoda Opis Typowe odpowiedzi
GET Pobiera okreslony zasob wedlug podanego identyfikatora 200 (OK) - z zasobem zwracanym
404 (Not Found) - jesli zasobu nie odnaleziono
POST Tworzy nowy zasob. Wykorzystywany do operacji nie wpisujacych sie w inne metody. Moze sluzyc do pobierania danych gdy potrzebne sa parametry w body 201 (Created) - Header Location powinien zawierac link do zasobu
409 (Conflict) - jesli zasob juz istnieje
PUT Aktualizuje (zastepuje) caly zasob. Moze tworzyc nowy zasob jesli jego ID jest znany 200 (OK) lub 204 (No Content)
404 (Not Found) - jesli nie odnaleziono ID
409 (Conflict) - jesli ID w ciele rozni sie od ID w sciezce
PATCH Aktualizuje czesc wskazanego zasobu (tylko wybrane pola) 200 (OK) lub 204 (No Content)
404 (Not Found) - jesli nie odnaleziono ID
409 (Conflict) - jesli ID w ciele rozni sie od ID w sciezce
DELETE Usuwa okreslony zasob wedlug identyfikatora 200 (OK) lub 204 (No Content)
404 (Not Found) - jesli nie odnaleziono ID
HEAD Jak GET, ale zwraca tylko naglowki (bez body) 200 (OK)
404 (Not Found)
OPTIONS Zwraca dostepne metody dla zasobu (uzywane w CORS) 200 (OK) lub 204 (No Content)

Charakterystyka metod:

Idempotentna - wielokrotne wywolanie daje ten sam efekt co pojedyncze (mozna bezpiecznie ponowic przy timeout).
Bezpieczna - nie zmienia stanu serwera, tylko odczytuje dane. Kazda metoda bezpieczna jest tez idempotentna.

Metoda Idempotentna Bezpieczna Request Body Response Body
GET
POST
PUT
DELETE
PATCH

24. Czym rozni sie PUT od PATCH?

🎯 Podstawy:
// Zasob poczatkowy
{
  "id": 1,
  "name": "Jan Kowalski",
  "email": "jan@example.com",
  "phone": "123456789"
}

// PUT /users/1 - zastepuje CALY zasob
// Musisz wyslac wszystkie pola!
{
  "name": "Jan Nowak",
  "email": "jan@example.com",
  "phone": "123456789"
}

// PATCH /users/1 - aktualizuje TYLKO podane pola
{
  "name": "Jan Nowak"
}
// Pozostale pola (email, phone) pozostaja bez zmian

25. Jak zaprojektowalbys REST API dla sklepu internetowego?

🎯 Podstawy:
# Produkty
GET    /api/products                    # lista produktow (z paginacja)
GET    /api/products/{id}               # szczegoly produktu
POST   /api/products                    # dodaj produkt (admin)
PUT    /api/products/{id}               # aktualizuj produkt
DELETE /api/products/{id}               # usun produkt

# Kategorie
GET    /api/categories                  # lista kategorii
GET    /api/categories/{id}/products    # produkty w kategorii

# Koszyk
GET    /api/cart                        # zawartosc koszyka
POST   /api/cart/items                  # dodaj do koszyka
PUT    /api/cart/items/{productId}      # zmien ilosc
DELETE /api/cart/items/{productId}      # usun z koszyka

# Zamowienia
GET    /api/orders                      # historia zamowien
GET    /api/orders/{id}                 # szczegoly zamowienia
POST   /api/orders                      # zloz zamowienie

# Filtrowanie i paginacja
GET /api/products?category=electronics&minPrice=100&page=0&size=20&sort=price,asc

26. Kody statusu HTTP - przyklady

🎯 Podstawy:

1xx - Informacyjne:

Kod Znaczenie Uzycie
100 Continue Serwer otrzymal naglowki, klient moze wyslac body
101 Switching Protocols Serwer akceptuje zmiane protokolu (np. na WebSocket)
102 Processing Serwer przetwarza zadanie (WebDAV) - zapobiega timeout
103 Early Hints Wczesne ladowanie zasobow (Link headers) przed pelna odpowiedzia

2xx - Sukces:

Kod Znaczenie Uzycie
200 OK GET, PUT, PATCH - sukces
201 Created POST - zasob utworzony
202 Accepted Zadanie przyjete do przetwarzania (async)
204 No Content DELETE - sukces bez tresci

3xx - Przekierowania:

Kod Znaczenie Uzycie
301 Moved Permanently Zasob przeniesiony na stale (SEO, nowy URL)
302 Found (Temporary Redirect) Tymczasowe przekierowanie
303 See Other Przekierowanie po POST (PRG pattern)
304 Not Modified Cache - zasob nie zmieniony, uzyj lokalnej kopii
307 Temporary Redirect Jak 302, ale zachowuje metode HTTP
308 Permanent Redirect Jak 301, ale zachowuje metode HTTP

4xx - Blad klienta:

Kod Znaczenie Uzycie
400 Bad Request Bledne dane wejsciowe
401 Unauthorized Brak/nieprawidlowe uwierzytelnienie
403 Forbidden Brak uprawnien
404 Not Found Zasob nie istnieje
409 Conflict Konflikt (np. duplikat)
422 Unprocessable Entity Blad walidacji

5xx - Blad serwera:

Kod Znaczenie Uzycie
500 Internal Server Error Nieobsluzony wyjatek
502 Bad Gateway Problem z upstream serwerem
503 Service Unavailable Serwer przeciazony/maintenance

27. Jak zabezpieczysz API? (JWT, OAuth2, API keys)

🎯 Podstawy:

1. JWT (JSON Web Token):

// Struktura: header.payload.signature

@PostMapping("/login")
public TokenResponse login(@RequestBody LoginRequest request) {
    // 1. Weryfikacja credentials
    // 2. Generowanie JWT
    String token = Jwts.builder()
        .setSubject(user.getUsername())
        .setExpiration(new Date(System.currentTimeMillis() + 86400000))
        .signWith(secretKey)
        .compact();
    return new TokenResponse(token);
}

// Klient wysyla: Authorization: Bearer <token>

Dodatkowe zabezpieczenia: HTTPS, Rate limiting, Input validation, CORS configuration, Audit logging

28. Co to jest CORS i jak go skonfigurowac?

🎯 Podstawy:

CORS (Cross-Origin Resource Sharing) - mechanizm pozwalajacy na zadania z innej domeny niz serwer.

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins("http://localhost:3000", "https://myapp.com")
            .allowedMethods("GET", "POST", "PUT", "DELETE")
            .allowedHeaders("*")
            .allowCredentials(true)
            .maxAge(3600);
    }
}

Microservices

🎬 Materiały wideo (PL):

29. Czym rozni sie architektura monolityczna od mikroserwisow?

🎯 Podstawy:
Cecha Monolit Mikroserwisy
Deployment Cala aplikacja naraz Niezalezny dla kazdego serwisu
Skalowanie Calosc Kazdy serwis osobno
Technologia Jedna dla calosci Rozne dla roznych serwisow
Komunikacja Wywolania metod Siec (HTTP, messaging)
Baza danych Wspolna Kazdy serwis ma wlasna
Zlozonosc Prostszy start Wieksza zlozonosc operacyjna

30. Jak mikroserwisy komunikuja sie ze soba?

🎯 Podstawy:
Metoda Uzycie Zalety Wady
REST CRUD, synchroniczne Prosty, standardowy Latency, coupling
Messaging (Kafka/RabbitMQ) Eventy, async Loose coupling, resilience Zlozonosc, eventual consistency
gRPC High-performance Szybki, typowany Mniej czytelny
// Producer - Kafka
@Service
public class OrderService {
    private final KafkaTemplate<String, OrderEvent> kafka;

    public void createOrder(Order order) {
        orderRepository.save(order);
        kafka.send("order-events", new OrderCreatedEvent(order));
    }
}

// Consumer w innym serwisie
@KafkaListener(topics = "order-events")
public void handleOrderCreated(OrderCreatedEvent event) {
    sendEmail(event.getCustomerEmail());
}

31. Co to jest API Gateway i jaka pelni role?

🎯 Podstawy:

API Gateway - punkt wejscia do systemu mikroserwisow.

+-------------------+ | API Gateway | Client -----------> | (np. nginx, | | Spring Cloud) | +---------+---------+ | +---------------------+---------------------+ v v v +---------------+ +---------------+ +---------------+ | Product Svc | | Order Svc | | User Svc | +---------------+ +---------------+ +---------------+

Funkcje: Routing, Load balancing, Authentication, Rate limiting, Caching, SSL termination, Request/Response transformation

32. Jak obsluzys transakcje rozproszone? (Saga pattern)

🎯 Podstawy:

W mikroserwisach nie ma wspolnej transakcji - kazdy serwis ma wlasna baze.

Saga Pattern

Saga Pattern - sekwencja lokalnych transakcji z kompensacjami (Eventual Consistency).

Zamowienie: 1. Order Service: Utworz zamowienie (status: PENDING) 2. Payment Service: Pobierz platnosc 3. Inventory Service: Zarezerwuj produkty 4. Order Service: Potwierdz zamowienie (status: CONFIRMED) Jesli krok 3 sie nie powiedzie: - Kompensacja 2: Zwroc platnosc - Kompensacja 1: Anuluj zamowienie

Implementacje: Choreography (zdarzenia) lub Orchestration (centralny koordynator)

Alternatywy dla Saga Pattern

1. Two-Phase Commit (2PC) - protokol zapewniajacy ACID w transakcjach rozproszonych.

FAZA 1: PREPARE (Glosowanie) ┌──────────────┐ │ COORDINATOR │───PREPARE───→ [Product DB] → VOTE YES/NO │ (Transaction │───PREPARE───→ [Order DB] → VOTE YES/NO │ Manager) │───PREPARE───→ [Payment DB] → VOTE YES/NO └──────────────┘ FAZA 2: COMMIT/ROLLBACK - Jesli WSZYSTKIE glosy = YES → COMMIT do wszystkich - Jesli JAKIKOLWIEK glos = NO → ROLLBACK do wszystkich
// Przyklad z Atomikos (JTA Transaction Manager)
@Bean
public JtaTransactionManager transactionManager() {
    return new JtaTransactionManager(
        new UserTransactionManager()
    );
}

@Transactional(transactionManager = "jtaTransactionManager")
public void createOrder(OrderRequest request) {
    productRepo.reserve(request);   // XA Resource 1
    orderRepo.save(order);           // XA Resource 2
    paymentRepo.create(payment);    // XA Resource 3
    // Automatyczny COMMIT lub ROLLBACK przez Atomikos
}

2. TCC (Try-Confirm-Cancel) - wzorzec z rezerwacja zasobow (soft-lock).

TRY PHASE: Rezerwacja zasobow ├─ Product: reserveStock() → status: RESERVED ├─ Order: createPending() → status: PENDING └─ Payment: holdFunds() → status: HOLD CONFIRM PHASE: Zatwierdzenie (jesli wszystko OK) ├─ Product: confirmReservation() → status: SOLD ├─ Order: confirmOrder() → status: CONFIRMED └─ Payment: capturePayment() → status: CAPTURED CANCEL PHASE: Anulowanie (jesli blad) ├─ Product: cancelReservation() → status: AVAILABLE ├─ Order: cancelOrder() → status: CANCELLED └─ Payment: releaseFunds() → status: RELEASED

Porownanie wzorcow

Cecha Saga 2PC TCC
Spojnosc Eventual Strong (ACID) Eventual
Dostepnosc Wysoka Niska (blocking) Wysoka
Wydajnosc Wysoka Niska (locks) Srednia
Izolacja Brak Pelna Soft locks
Single Point of Failure Nie Tak (coordinator) Nie
Przypadek uzycia Mikroserwisy Monolit / 2-3 DB Rezerwacje (hotele, bilety)

Kiedy uzywac:

33. Co to jest service discovery?

🎯 Podstawy:

Service Discovery - mechanizm automatycznego wykrywania lokalizacji serwisow.

Narzedzia: Netflix Eureka, Consul, Kubernetes DNS

# application.yml serwisu
eureka:
  client:
    serviceUrl:
      defaultZone: http://eureka:8761/eureka/

// Wywolanie po nazwie serwisu (nie IP)
restTemplate.getForObject("http://product-service/api/products/1", Product.class);

34. Jak monitorowac mikroserwisy? (logi, metryki, tracing)

🎯 Podstawy:

Trzy filary obserwowalnosci:

  1. Logi (co sie wydarzylo) - ELK Stack / Loki + Grafana
  2. Metryki (ile/jak szybko) - Prometheus + Grafana
  3. Tracing (sciezka zadania przez serwisy) - Zipkin / Jaeger
# Spring Boot Actuator + Micrometer
management:
  endpoints:
    web:
      exposure:
        include: health, metrics, prometheus
  metrics:
    export:
      prometheus:
        enabled: true

Docker / DevOps

🎬 Materiały wideo (PL):

35. Czym jest Docker i jakie problemy rozwiazuje?

🎯 Podstawy:

Docker - platforma do konteneryzacji aplikacji.

Problemy ktore rozwiazuje:

36. Czym rozni sie obraz od kontenera?

🎯 Podstawy:
Obraz (Image) Kontener (Container)
Szablon (blueprint) Uruchomiona instancja obrazu
Niezmienialny (immutable) Ma swoj stan (mozna zapisywac)
Warstwy tylko do odczytu Warstwa zapisu na gorze
docker build / docker pull docker run
Jak klasa w OOP Jak obiekt w OOP

37. Do czego sluzy docker-compose?

🎯 Podstawy:

Docker Compose - narzedzie do definiowania i uruchamiania wielu kontenerow.

# docker-compose.yml
version: '3.8'

services:
  product-service:
    build: ./services/product-service
    ports:
      - "8081:8080"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/products
    depends_on:
      - db

  db:
    image: postgres:15
    environment:
      POSTGRES_PASSWORD: secret
    volumes:
      - postgres-data:/var/lib/postgresql/data

volumes:
  postgres-data:

38. Jak zoptymalizujesz Dockerfile?

🎯 Podstawy:
# Stage 1: Build
FROM eclipse-temurin:21-jdk AS builder
WORKDIR /app

# Najpierw kopiuj tylko pliki zaleznosci (lepszy cache)
COPY pom.xml .
COPY .mvn .mvn
COPY mvnw .
RUN ./mvnw dependency:go-offline

# Potem kod zrodlowy
COPY src ./src
RUN ./mvnw package -DskipTests

# Stage 2: Runtime (mniejszy obraz)
FROM eclipse-temurin:21-jre
WORKDIR /app

# Non-root user
RUN addgroup --system app && adduser --system --group app
USER app

COPY --from=builder /app/target/*.jar app.jar

EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
Techniki optymalizacji: Multi-stage builds (JDK vs JRE), Layer caching, Mniejszy base image (alpine), Non-root user, .dockerignore

Testowanie

🎬 Materiały wideo (PL):

39. Czym rozni sie test jednostkowy od integracyjnego?

🎯 Podstawy:
Cecha Test jednostkowy Test integracyjny
Zakres Pojedyncza klasa/metoda Wiele komponentow razem
Zaleznosci Mockowane Prawdziwe (DB, HTTP)
Szybkosc Bardzo szybkie (ms) Wolniejsze (sekundy)
Izolacja Pelna Czesciowa
Cel Logika biznesowa Wspolpraca komponentow

40. Do czego sluzy Mockito?

🎯 Podstawy:

Mockito - biblioteka do tworzenia mockow (atrap) obiektow w testach.

@ExtendWith(MockitoExtension.class)
class ProductServiceTest {

    @Mock
    private ProductRepository productRepository;

    @InjectMocks
    private ProductService productService;

    @Test
    void shouldReturnProduct() {
        // given - konfiguracja mockow
        Product product = new Product(1L, "Laptop");
        when(productRepository.findById(1L)).thenReturn(Optional.of(product));

        // when
        ProductDTO result = productService.findById(1L);

        // then
        assertThat(result.getName()).isEqualTo("Laptop");
        verify(productRepository).findById(1L);
    }
}

Glowne funkcje: @Mock, @InjectMocks, when(...).thenReturn(...), verify(...), @Spy, @Captor

41. Co to jest TDD?

🎯 Podstawy:

TDD (Test-Driven Development) - technika, gdzie najpierw piszesz test, potem kod.

+-------------------+ | RED | <-- Napisz test (ktory nie przechodzi) | Failing test | +---------+---------+ | v +-------------------+ | GREEN | <-- Napisz minimalny kod zeby test przeszedl | Passing test | +---------+---------+ | v +-------------------+ | REFACTOR | <-- Popraw kod (testy nadal przechodza) | Clean code | +---------+---------+ | +-------> Powtorz dla nastepnej funkcjonalnosci
Zalety TDD: Wymusza przemyslenie API przed implementacja, mniejsze ryzyko regresji, dokumentacja przez testy, prostszy kod

42. Jak testujesz kontrolery w Spring Boot?

🎯 Podstawy:
@WebMvcTest(ProductController.class)  // laduje tylko warstwe web
class ProductControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean  // mock dla beana w kontekscie Springa
    private ProductService productService;

    @Test
    void shouldReturnProductById() throws Exception {
        // given
        ProductDTO product = new ProductDTO(1L, "Laptop", BigDecimal.valueOf(999));
        when(productService.findById(1L)).thenReturn(product);

        // when & then
        mockMvc.perform(get("/api/products/1")
                .contentType(MediaType.APPLICATION_JSON))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$.id").value(1))
            .andExpect(jsonPath("$.name").value("Laptop"));
    }
}

Pytania praktyczne

🎬 Materiały wideo (PL):

43. Jak znajdziesz i naprawisz memory leak?

🎯 Podstawy:

Memory Leak (wyciek pamieci) - sytuacja, gdy aplikacja alokuje pamiec, ale nigdy jej nie zwalnia, mimo ze juz jej nie potrzebuje. W Javie oznacza to obiekty, ktore nie sa uzywane, ale Garbage Collector nie moze ich usunac, bo wciaz istnieja do nich referencje.

MEMORY LEAK W JAVIE: Normalna sytuacja: Memory Leak: ┌─────────┐ ┌─────────┐ │ Root │─x─→ [Obiekt] │ Root │────→ [Kolekcja] ────→ [Obiekt] └─────────┘ (GC usunie) └─────────┘ (statyczna) (nigdy nie usuniety!) │ └──→ [Obiekt] ──→ [Obiekt] ... (rosnie w nieskonczonosc)

1. Identyfikacja:

# Monitoring heap
jstat -gc <pid> 1000

# Heap dump przy OutOfMemoryError
java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp/heap.hprof -jar app.jar

2. Typowe przyczyny:

Przyklady kodu - JAK NIE robic vs JAK robic:

1. Statyczna kolekcja (cache bez limitu):

// ZLE - memory leak! Kolekcja rosnie w nieskonczonosc
public class UserCache {
    private static final Map<Long, User> cache = new HashMap<>();

    public void addUser(User user) {
        cache.put(user.getId(), user);  // Nigdy nie usuwane!
    }
}

// DOBRZE - ograniczony cache z LRU eviction
public class UserCache {
    private static final int MAX_SIZE = 1000;
    private static final Map<Long, User> cache = new LinkedHashMap<>(MAX_SIZE, 0.75f, true) {
        @Override
        protected boolean removeEldestEntry(Map.Entry<Long, User> eldest) {
            return size() > MAX_SIZE;  // Usuwa najstarszy gdy przekroczy limit
        }
    };
}

// JESZCZE LEPIEJ - Caffeine/Guava Cache
Cache<Long, User> cache = Caffeine.newBuilder()
    .maximumSize(1000)
    .expireAfterWrite(10, TimeUnit.MINUTES)
    .build();

2. Niezamkniete zasoby (InputStream, Connection):

// ZLE - memory leak! Stream nigdy nie zamkniety
public String readFile(String path) throws IOException {
    FileInputStream fis = new FileInputStream(path);
    byte[] data = fis.readAllBytes();
    return new String(data);
    // fis.close() NIGDY nie wywolane - wyciek!
}

// DOBRZE - try-with-resources (automatyczne zamkniecie)
public String readFile(String path) throws IOException {
    try (FileInputStream fis = new FileInputStream(path)) {
        byte[] data = fis.readAllBytes();
        return new String(data);
    }  // fis.close() wywolane automatycznie (nawet przy uzyciu wyjatku)
}

3. ThreadLocal bez czyszczenia:

// ZLE - memory leak w aplikacji webowej!
public class UserContext {
    private static final ThreadLocal<User> currentUser = new ThreadLocal<>();

    public static void setUser(User user) {
        currentUser.set(user);  // Watek z puli trzyma referencje na zawsze!
    }
}

// DOBRZE - zawsze czyscimy w finally lub uzyj filtra
public class UserContext {
    private static final ThreadLocal<User> currentUser = new ThreadLocal<>();

    public static void setUser(User user) { currentUser.set(user); }
    public static void clear() { currentUser.remove(); }  // KRYTYCZNE!
}

// W filtrze Spring:
@Component
public class UserContextFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) {
        try {
            UserContext.setUser(extractUser(req));
            chain.doFilter(req, res);
        } finally {
            UserContext.clear();  // ZAWSZE czyscimy po uzyciu zadania
        }
    }
}

4. Listenery/Observery bez wyrejestrowania:

// ZLE - memory leak! Listener trzyma referencje do obiektu
@Service
public class OrderService {
    @Autowired
    private EventPublisher publisher;

    @PostConstruct
    public void init() {
        publisher.addListener(this::onEvent);  // Zarejestrowany na zawsze!
    }
}

// DOBRZE - wyrejestrowanie w @PreDestroy
@Service
public class OrderService {
    @Autowired
    private EventPublisher publisher;
    private Consumer<Event> listener;

    @PostConstruct
    public void init() {
        listener = this::onEvent;
        publisher.addListener(listener);
    }

    @PreDestroy
    public void cleanup() {
        publisher.removeListener(listener);  // Wyrejestrowanie!
    }
}

5. Klasy wewnetrzne (inner class) trzymajace referencje:

// ZLE - non-static inner class trzyma referencje do outer class
public class HeavyObject {
    private byte[] data = new byte[10_000_000];  // 10MB

    public Runnable createTask() {
        return new Runnable() {  // Anonimowa klasa trzyma ref do HeavyObject!
            public void run() { System.out.println("Task"); }
        };
    }
}

// DOBRZE - static nested class lub lambda bez referencji
public class HeavyObject {
    private byte[] data = new byte[10_000_000];

    public Runnable createTask() {
        return () -> System.out.println("Task");  // Lambda bez ref do this
    }

    // Lub static nested class:
    private static class MyTask implements Runnable {
        public void run() { System.out.println("Task"); }
    }
}

44. Jak zoptymalizujesz wolne zapytanie SQL?

🎯 Podstawy:

W srodowiskach o duzym obciazeniu, optymalizacja wydajnosci transakcji jest niezbedna. Im krocej trwa zapytanie, tym krocej trzyma locki.

-- Analiza z EXPLAIN ANALYZE
EXPLAIN ANALYZE
SELECT * FROM orders WHERE created_at > '2024-01-01';

Typowe problemy i rozwiazania:

1. Indeksowanie

Poprawia wydajnosc zapytan, ale wymaga rownowagi - zbyt wiele indeksow wydluza czas zapisu (INSERT/UPDATE).

-- Zamiast wolnego zapytania:
SELECT * FROM orders
WHERE user_id = 123
ORDER BY created_at DESC;

-- Utworz indeks kompozytowy:
CREATE INDEX idx_orders_user_created
ON orders(user_id, created_at DESC);

W JPA/Hibernate:

@Entity
@Table(
    name = "orders",
    indexes = {
        @Index(name = "idx_orders_user_created", columnList = "user_id, created_at")
    }
)
public class Order {
    // ...
}

2. Unikanie SELECT *

Pobieraj tylko potrzebne kolumny - zmniejsza transfer danych i obciazenie pamieci.

-- ZLE: pobiera wszystkie kolumny
SELECT * FROM orders WHERE user_id = 123;

-- DOBRZE: tylko potrzebne kolumny
SELECT id, status, created_at FROM orders WHERE user_id = 123;

W JPA - projekcja do DTO:

// DTO
public record OrderSummaryDto(
    Long id,
    OrderStatus status,
    LocalDateTime createdAt
) {}

// Repository - projekcja zamiast calej encji
@Query("""
    SELECT new projekt.dto.OrderSummaryDto(
        o.id,
        o.status,
        o.createdAt
    )
    FROM Order o
    WHERE o.userId = :userId
""")
List<OrderSummaryDto> findOrderSummariesByUserId(@Param("userId") Long userId);

3. Batching - unikanie N+1 / petli

Zamiast wielu pojedynczych zapytan, uzyj jednego z IN (...).

// ZLE - N zapytan (petla)
List<Long> userIds = List.of(1L, 2L, 3L);
List<Order> allOrders = new ArrayList<>();

for (Long userId : userIds) {
    allOrders.addAll(orderRepository.findByUserId(userId));
}
// Generuje N zapytan:
// SELECT * FROM orders WHERE user_id = 1;
// SELECT * FROM orders WHERE user_id = 2;
// SELECT * FROM orders WHERE user_id = 3;

// DOBRZE - jedno zapytanie z IN
List<Order> orders = orderRepository.findByUserIdIn(userIds);

// Repository:
interface OrderRepository extends JpaRepository<Order, Long> {
    List<Order> findByUserIdIn(List<Long> userIds);
}
// Generuje: SELECT * FROM orders WHERE user_id IN (1, 2, 3);

4. Przetwarzanie wsadowe (Batch Insert/Update)

Grupuje operacje zapisu w celu zmniejszenia liczby round-tripow do bazy.

// ZLE - N operacji INSERT
for (Order o : orders) {
    orderRepository.save(o);  // Kazdy save = oddzielny INSERT
}

// DOBRZE - batch insert
orderRepository.saveAll(orders);  // Jeden batch

// Konfiguracja w application.yml:
spring:
  jpa:
    properties:
      hibernate:
        jdbc:
          batch_size: 50
        order_inserts: true
        order_updates: true

5. Pula polaczen (Connection Pool)

Ponowne wykorzystanie polaczen zamiast tworzenia nowych (kosztowna operacja).

# HikariCP - domyslny w Spring Boot
spring:
  datasource:
    hikari:
      maximum-pool-size: 20        # Max polaczen w puli
      minimum-idle: 5             # Min polaczen gotowych
      connection-timeout: 30000   # Timeout na pobranie polaczenia (ms)
      idle-timeout: 600000        # Czas bezczynnosci przed zamknieciem

6. Kontrola wspolbieznosci - blokowanie na poziomie wiersza

Row-level locking zamiast table-level - pozwala na rownoczesne transakcje na roznych wierszach.

-- Row-level lock (tylko wiersz id=1)
SELECT * FROM orders WHERE id = 1 FOR UPDATE;

-- NOWAIT - nie czekaj, rzuc blad jesli zablokowane
SELECT * FROM orders WHERE id = 1 FOR UPDATE NOWAIT;

-- SKIP LOCKED - pomin zablokowane wiersze (dobre dla queue)
SELECT * FROM tasks WHERE status = 'PENDING'
ORDER BY created_at LIMIT 1 FOR UPDATE SKIP LOCKED;

7. Rownowazenie obciazenia (Read Replicas)

Rozklad obciazenia przez replikacje - zapisy do mastera, odczyty z replik.

┌─────────────┐ │ Master │◄──── INSERT, UPDATE, DELETE │ (write) │ └──────┬──────┘ │ replikacja ▼ ┌─────────────┐ │ Replica 1 │◄──── SELECT (read-only) └─────────────┘ ┌─────────────┐ │ Replica 2 │◄──── SELECT (read-only) └─────────────┘
// Spring - @Transactional(readOnly = true) kieruje na replike
@Transactional(readOnly = true)
public List<Order> findAllOrders() {
    return orderRepository.findAll();  // Idzie na replike
}

@Transactional
public void createOrder(Order order) {
    orderRepository.save(order);  // Idzie na mastera
}

Podsumowanie technik optymalizacji

Technika Problem Rozwiazanie
Indeksowanie Wolne wyszukiwanie CREATE INDEX na WHERE, JOIN, ORDER BY
Projekcja SELECT * pobiera za duzo DTO z tylko potrzebnymi polami
Batching N+1 / petla zapytan findByIdIn(), saveAll()
Connection Pool Kosztowne tworzenie polaczen HikariCP z odpowiednim pool size
Row-level locking Blokowanie calej tabeli FOR UPDATE, SKIP LOCKED
Read Replicas Master przeciazony @Transactional(readOnly=true)

45. Zaprojektuj system kolejkowania zadan

🎯 Podstawy:
+-------------+ +-------------+ +-------------+ | Producer |---->| Queue |---->| Workers | | (API) | | (Redis/ | | (Consumer) | +-------------+ | Kafka) | +-------------+ +-------------+ | v +-------------+ | DB | | (status) | +-------------+

Kluczowe elementy:

46. Live coding: endpoint CRUD

🎯 Podstawy:
// Entity
@Entity
@Data
public class Product {
    @Id @GeneratedValue
    private Long id;
    @NotBlank
    private String name;
    @NotNull @Positive
    private BigDecimal price;
}

// Controller
@RestController
@RequestMapping("/api/products")
@RequiredArgsConstructor
public class ProductController {

    private final ProductService service;

    @GetMapping
    public Page<ProductResponse> getAll(Pageable pageable) {
        return service.findAll(pageable);
    }

    @GetMapping("/{id}")
    public ProductResponse getById(@PathVariable Long id) {
        return service.findById(id);
    }

    @PostMapping
    @ResponseStatus(HttpStatus.CREATED)
    public ProductResponse create(@Valid @RequestBody ProductRequest request) {
        return service.create(request);
    }

    @PutMapping("/{id}")
    public ProductResponse update(@PathVariable Long id,
                                    @Valid @RequestBody ProductRequest request) {
        return service.update(id, request);
    }

    @DeleteMapping("/{id}")
    @ResponseStatus(HttpStatus.NO_CONTENT)
    public void delete(@PathVariable Long id) {
        service.delete(id);
    }
}

Naglowki HTTP

🎬 Materiały wideo (PL):

47. Jakie sa najwazniejsze naglowki HTTP i do czego sluza?

🎯 Podstawy:

Naglowki HTTP to metadane przesylane miedzy klientem a serwerem. Dziela sie na kategorie:

Naglowki zadania (Request Headers):

Naglowek Opis Przyklad
Authorization Dane uwierzytelniajace (token, credentials) Bearer eyJhbGciOiJIUzI1NiIs...
Content-Type Typ MIME wysylanej tresci application/json
Accept Jakie typy odpowiedzi klient akceptuje application/json, text/html
Accept-Language Preferowany jezyk odpowiedzi pl-PL, en-US;q=0.9
Accept-Encoding Akceptowane kompresje gzip, deflate, br
User-Agent Informacje o kliencie (przegladarka, OS) Mozilla/5.0 (Windows NT 10.0)...
Host Domena docelowa (wymagany w HTTP/1.1) api.example.com
Cookie Ciasteczka wysylane do serwera session_id=abc123; theme=dark
Origin Zrodlo zadania (CORS) https://myapp.com
Referer URL strony, z ktorej przyszlo zadanie https://google.com/search?q=...
X-Requested-With Identyfikuje zadania AJAX XMLHttpRequest
If-None-Match Warunkowe zadanie (cache) - ETag "abc123"
If-Modified-Since Warunkowe zadanie - data modyfikacji Wed, 21 Oct 2024 07:28:00 GMT

Naglowki odpowiedzi (Response Headers):

Naglowek Opis Przyklad
Content-Type Typ MIME odpowiedzi application/json; charset=utf-8
Content-Length Rozmiar odpowiedzi w bajtach 1234
Content-Encoding Uzyta kompresja gzip
Set-Cookie Ustawia ciasteczko w przegladarce session=abc; HttpOnly; Secure
Location URL przekierowania (3xx) https://example.com/new-page
Cache-Control Dyrektywy cache max-age=3600, must-revalidate
ETag Identyfikator wersji zasobu (cache) "abc123"
Last-Modified Data ostatniej modyfikacji Wed, 21 Oct 2024 07:28:00 GMT
Expires Kiedy cache wygasa Thu, 01 Dec 2024 16:00:00 GMT
WWW-Authenticate Wymagana metoda uwierzytelnienia (401) Bearer realm="api"

Naglowki CORS:

Naglowek Opis Przyklad
Access-Control-Allow-Origin Dozwolone originy https://myapp.com lub *
Access-Control-Allow-Methods Dozwolone metody HTTP GET, POST, PUT, DELETE
Access-Control-Allow-Headers Dozwolone naglowki w zadaniu Content-Type, Authorization
Access-Control-Allow-Credentials Czy wysylac cookies true
Access-Control-Max-Age Jak dlugo cachowac preflight 3600
Access-Control-Expose-Headers Naglowki widoczne dla JS X-Custom-Header

Naglowki bezpieczenstwa:

Naglowek Opis Przyklad
Strict-Transport-Security Wymusza HTTPS (HSTS) max-age=31536000; includeSubDomains
X-Content-Type-Options Blokuje MIME sniffing nosniff
X-Frame-Options Ochrona przed clickjacking DENY lub SAMEORIGIN
X-XSS-Protection Filtr XSS przegladarki 1; mode=block
Content-Security-Policy Polityka ladowania zasobow default-src 'self'; script-src 'self'
Referrer-Policy Co wysylac w Referer strict-origin-when-cross-origin

48. Jak dziala cacheowanie z naglowkami HTTP?

🎯 Podstawy:
Pierwsze zadanie: Client ----GET /api/products----> Server Client <---200 OK---------------< Server ETag: "abc123" Cache-Control: max-age=3600 Kolejne zadanie (przed wygasnieciem cache): Client: uzywa lokalnej kopii, nie wysyla zadania Kolejne zadanie (po wygasnieciu cache): Client ----GET /api/products----> Server If-None-Match: "abc123" Client <---304 Not Modified-----< Server (zasob nie zmieniony) lub Client <---200 OK + nowe dane---< Server (zasob zmieniony, nowy ETag)
// Spring - ustawianie naglowkow cache
@GetMapping("/products/{id}")
public ResponseEntity<Product> getProduct(@PathVariable Long id) {
    Product product = productService.findById(id);

    return ResponseEntity.ok()
        .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS))
        .eTag(String.valueOf(product.hashCode()))
        .body(product);
}

Autentykacja i Autoryzacja z Keycloak

🎬 Materiały wideo:

⚠️ Polskich filmów wprost o Keycloak jest niewiele — w praktyce warto sięgnąć po anglojęzyczne JavaTechie/Amigoscode.

49. Czym rozni sie autentykacja od autoryzacji?

🎯 Podstawy:
Cecha Autentykacja (Authentication) Autoryzacja (Authorization)
Pytanie "Kim jestes?" "Co mozesz robic?"
Cel Weryfikacja tozsamosci Sprawdzenie uprawnien
Kiedy Przed autoryzacja Po autentykacji
Przyklad Login + haslo, token JWT Role: ADMIN, USER, uprawnienia
Blad HTTP 401 Unauthorized 403 Forbidden

50. Co to jest Keycloak i jakie problemy rozwiazuje?

🎯 Podstawy:

Keycloak - open-source'owy serwer Identity and Access Management (IAM) od Red Hat.

Funkcje:

+-------------+ +-------------+ +-------------+ | Client | | Keycloak | | Backend | | (Frontend) | | Server | | (API) | +------+------+ +------+------+ +------+------+ | | | | 1. Login page | | |------------------>| | | | | | 2. Credentials | | |------------------>| | | | | | 3. Access Token | | | + Refresh Token | | |<------------------| | | | | | 4. API Request + Token | |-------------------------------------->| | | | | | 5. Validate Token| | |<------------------| | | | | | 6. Token valid | | |------------------>| | | | | 7. Response | |<--------------------------------------|

50a. Jakie sa ustawienia klienta w Keycloak (Capability Config)?

W Keycloak kazdy klient ma Capability config - ustawienia okreslajace jak klient moze sie uwierzytelniac i jakie ma uprawnienia.

Czym jest client_id i client_secret?

Parametr Opis Analogia Bezpieczenstwo
client_id Publiczny identyfikator aplikacji w Keycloak. Unikatowa nazwa klienta zarejestrowanego w realm. Jak login/username - mozna go pokazac publicznie PUBLICZNY - moze byc widoczny w kodzie frontendu, URL-ach
client_secret Tajny klucz znany tylko aplikacji i Keycloak. Generowany automatycznie przez Keycloak (zakladka Credentials). Jak haslo - musi byc trzymany w sekrecie TAJNY - tylko w backendzie, w zmiennych srodowiskowych, NIGDY w kodzie frontendu!
# Gdzie znajdziesz te wartosci w Keycloak:
# 1. Zaloguj sie do Keycloak Admin Console
# 2. Wybierz realm (np. car-shop)
# 3. Clients -> wybierz klienta

# client_id:
#   Zakladka "Settings" -> pole "Client ID"
#   Np: api-communication-client

# client_secret:
#   Zakladka "Credentials" -> pole "Client secret"
#   Np: BeY47DCttqijpIOaU9oF2QVRbR7EXzHF
#   (widoczne tylko gdy Client authentication = ON)
POROWNANIE: Public vs Confidential Client PUBLIC CLIENT (frontend) CONFIDENTIAL CLIENT (backend) ================================ ================================ client_id: frontend-app client_id: api-service client_secret: BRAK client_secret: BeY47DC... Request do Keycloak: Request do Keycloak: POST /token POST /token grant_type=authorization_code grant_type=client_credentials client_id=frontend-app client_id=api-service code=abc123 client_secret=BeY47DC... redirect_uri=http://... Kto moze uzywac? Kto moze uzywac? -> Kazdy kto zna client_id -> Tylko ten kto zna secret (widoczny w przegladarce) (ukryty na serwerze)
Dlaczego frontend nie uzywa client_secret?
Kod JavaScript w przegladarce jest widoczny dla kazdego (View Source, DevTools). Gdybys umieścił tam secret, kazdy moglby go skopiowac i podszyc sie pod Twoja aplikacje. Dlatego frontendy uzywaja public clients i polegaja na innych mechanizmach bezpieczenstwa (PKCE, redirect_uri validation).

Client authentication (On/Off)

Ustawienie Opis Kiedy uzywac
ON (Confidential) Klient musi podac client_secret przy kazdym zadaniu tokena. Secret jest generowany przez Keycloak. Aplikacje backendowe (server-to-server), gdzie secret mozna bezpiecznie przechowac
OFF (Public) Klient NIE potrzebuje sekretu. Kazdy moze uzywac client_id. Aplikacje frontendowe (SPA, mobile), gdzie nie mozna ukryc sekretu

Authorization (On/Off)

Ustawienie Opis
ON Wlacza zaawansowane zarzadzanie uprawnieniami (policies, permissions, resources). Pozwala na fine-grained access control - np. "user X moze edytowac tylko swoje zasoby".
OFF Prosta autoryzacja oparta tylko na rolach (RBAC). Wystarczajace dla wiekszosci aplikacji.

Authentication flow - typy przeplywow

Flow Opis Kiedy uzywac
Standard flow
(Authorization Code)
1. Uzytkownik przekierowany do Keycloak
2. Loguje sie (login + haslo)
3. Keycloak zwraca authorization_code
4. Aplikacja wymienia code na tokeny
Aplikacje frontendowe z logowaniem uzytkownika (SPA, web apps). Najbezpieczniejszy flow!
Direct access grants
(Resource Owner Password)
Aplikacja bezposrednio wysyla login i haslo uzytkownika do Keycloak.
POST /token z grant_type=password
Legacy aplikacje, testowanie. NIE ZALECANE w produkcji - haslo przechodzi przez aplikacje!
Service accounts
(Client Credentials)
Aplikacja uwierzytelnia sie sama soba (nie w imieniu uzytkownika).
POST /token z grant_type=client_credentials
Komunikacja backend-to-backend, mikroserwisy, batch jobs
Implicit flow Token zwracany bezposrednio w URL (bez wymiany code). Przestarzaly! NIE UZYWAC - zastapiony przez Standard flow + PKCE

Przyklad: Dwa rozne klienty w jednym systemie

KLIENT 1: Frontend (React/Angular) KLIENT 2: Backend Service ========================================== ========================================== Client authentication: OFF (public) Client authentication: ON (confidential) Authorization: OFF Authorization: OFF Standard flow: ON Standard flow: OFF Direct access grants: OFF Direct access grants: OFF Service accounts: OFF Service accounts: ON Uzytkownik loguje sie przez formularz Serwis uzywa client_credentials Keycloak -> dostaje token z rolami do komunikacji z innym serwisem
# KLIENT 1: Frontend - uzytkownik loguje sie przez przegladarke
# Ustawienia w Keycloak:
#   - Client authentication: OFF
#   - Standard flow: ON
#   - Valid redirect URIs: http://localhost:3000/*

# Frontend (React) - przekierowanie do Keycloak
const loginUrl = `
  https://keycloak.example.com/realms/car-shop/protocol/openid-connect/auth
  ?client_id=frontend-client
  &response_type=code
  &redirect_uri=http://localhost:3000/callback
  &scope=openid`;

window.location.href = loginUrl;
# KLIENT 2: Backend service - komunikacja miedzy mikroserwisami
# Ustawienia w Keycloak:
#   - Client authentication: ON
#   - Service accounts roles: ON
#   - Standard flow: OFF

# application.yml
spring:
  security:
    oauth2:
      client:
        registration:
          api-communication-client:
            client-id: api-communication-client
            client-secret: BeY47DCttqijpIOaU9oF2QVRbR7EXzHF  # z Keycloak -> Credentials
            authorization-grant-type: client_credentials
            scope: openid
        provider:
          keycloak:
            token-uri: https://keycloak.example.com/realms/car-shop/protocol/openid-connect/token
Wskazowka: Jesli Twoja aplikacja backendowa musi komunikowac sie z innymi serwisami (np. pobierac dane z innego mikroserwisu), uzyj client_credentials grant. Token nie reprezentuje uzytkownika, ale sam serwis. Role przypisujesz do "Service Account" klienta w Keycloak.

51. Jak skonfigurowac Spring Boot z Keycloak?

🎯 Podstawy:
# application.yml
spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: http://keycloak:8080/realms/my-realm
          jwk-set-uri: http://keycloak:8080/realms/my-realm/protocol/openid-connect/certs
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        return http
            .csrf(csrf -> csrf.disable())
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/api/public/**").permitAll()
                .requestMatchers("/api/admin/**").hasRole("ADMIN")
                .requestMatchers("/api/user/**").hasAnyRole("USER", "ADMIN")
                .anyRequest().authenticated()
            )
            .oauth2ResourceServer(oauth2 -> oauth2
                .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthConverter()))
            )
            .sessionManagement(session ->
                session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
            .build();
    }

    // Konwersja rol z Keycloak do Spring Security
    @Bean
    public JwtAuthenticationConverter jwtAuthConverter() {
        JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
        converter.setAuthoritiesClaimName("realm_access.roles");
        converter.setAuthorityPrefix("ROLE_");

        JwtAuthenticationConverter jwtConverter = new JwtAuthenticationConverter();
        jwtConverter.setJwtGrantedAuthoritiesConverter(converter);
        return jwtConverter;
    }
}

52. Jak wyglada struktura tokena JWT z Keycloak?

🎯 Podstawy:
// JWT sklada sie z 3 czesci: HEADER.PAYLOAD.SIGNATURE

// HEADER (algorytm i typ)
{
  "alg": "RS256",
  "typ": "JWT",
  "kid": "key-id-123"
}

// PAYLOAD (claims - dane)
{
  "exp": 1699999999,           // expiration time
  "iat": 1699996399,           // issued at
  "iss": "http://keycloak:8080/realms/my-realm",  // issuer
  "sub": "user-uuid-123",     // subject (user ID)
  "aud": "my-client",          // audience
  "typ": "Bearer",
  "azp": "my-client",          // authorized party
  "preferred_username": "jan.kowalski",
  "email": "jan@example.com",
  "realm_access": {
    "roles": ["USER", "ADMIN"]
  },
  "resource_access": {
    "my-client": {
      "roles": ["view-products", "edit-products"]
    }
  }
}

// SIGNATURE - weryfikuje integralnosc tokena
// RSASHA256(base64(header) + "." + base64(payload), privateKey)

53. Czym rozni sie Access Token od Refresh Token?

🎯 Podstawy:
Cecha Access Token Refresh Token
Cel Autoryzacja dostepu do zasobow Odswiezenie Access Tokena
Czas zycia Krotki (5-15 minut) Dlugi (dni/tygodnie)
Gdzie wysylany Do Resource Server (API) Tylko do Authorization Server (Keycloak)
Przechowywanie Pamiec (JS), localStorage HttpOnly Cookie (bezpieczniej)
Zawiera Dane uzytkownika, role, uprawnienia Tylko identyfikator sesji
// Odswiezanie tokena
POST /realms/my-realm/protocol/openid-connect/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=eyJhbGciOiJIUzI1NiIs...
&client_id=my-client
&client_secret=secret123

Haszowanie, Szyfrowanie i Kodowanie

🎬 Materiały wideo (PL):

54. Czym rozni sie haszowanie od szyfrowania i kodowania?

🎯 Podstawy:
Cecha Haszowanie Szyfrowanie Kodowanie
Odwracalnosc NIE (jednokierunkowe) TAK (z kluczem) TAK (bez klucza)
Cel Weryfikacja integralnosci, hasla Ochrona poufnosci Transformacja formatu
Klucz Nie wymaga Wymaga Nie wymaga
Uzycie Hasla, sumy kontrolne, podpisy Dane wrażliwe, komunikacja URL, Base64, Unicode
Przyklady SHA-256, bcrypt, Argon2 AES, RSA, ChaCha20 Base64, URL encoding, UTF-8
HASZOWANIE (jednokierunkowe): "password123" --[SHA-256]--> "ef92b778..." (zawsze ten sam wynik) NIE MOZNA odzyskac "password123" SZYFROWANIE (dwukierunkowe): "secret data" --[AES + klucz]--> "x8Kj2m..." --[AES + klucz]--> "secret data" ENCRYPT DECRYPT KODOWANIE (transformacja): "Hello World" --[Base64]--> "SGVsbG8gV29ybGQ=" --[Base64]--> "Hello World" ENCODE DECODE

55. Jakie algorytmy haszowania nalezy znac?

🎯 Podstawy:

Do hasel (wolne, z sola):

Algorytm Opis Zalecany
bcrypt Adaptacyjny, z wbudowana sola, konfigurowalny koszt TAK
Argon2 Zwyciesca Password Hashing Competition, odporny na GPU TAK (najlepszy)
scrypt Memory-hard, odporny na ataki sprzetowe TAK
PBKDF2 Starszy standard, wiele iteracji Akceptowalny
MD5, SHA-1 Szybkie, zlamane kryptograficznie NIE do hasel!

Do integralnosci danych (szybkie):

Algorytm Dlugosc Uzycie
SHA-256 256 bit Podpisy cyfrowe, JWT, sumy kontrolne
SHA-512 512 bit Wyzsze bezpieczenstwo
SHA-3 256/512 bit Najnowszy standard NIST
HMAC Zalezna od funkcji Weryfikacja z kluczem (API signatures)
// Spring Security - haszowanie hasla z bcrypt
@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(12); // cost factor 12
}

// Uzycie
String hash = passwordEncoder.encode("password123");
// $2a$12$LQv3c1yqBWVHxkd0LHAkCOYz6TtxMQJqhN8/X4.mfIgPLGCOqK6Fi

boolean matches = passwordEncoder.matches("password123", hash); // true

Co znaczy "odporny na GPU"?
Algorytm jest zaprojektowany tak, aby wymagac duzej ilosci pamieci RAM (memory-hard). Karty GPU maja ogromna moc obliczeniowa, ale ograniczona pamiec na pojedynczy watek, przez co nie moga efektywnie wykonywac milionow prob haszowania rownolegle.

Ataki na hasla – co warto znac?

1. Rainbow Table Attack

Atak polega na wykorzystaniu gotowych tabel zawierajacych pary: hash → oryginalne haslo. Atakujacy nie musi liczyc hasha – tylko sprawdza go w ogromnej bazie.

Dlaczego to dziala?

Jak sie bronic?

Bez soli: "password" → SHA256 → 5e884898... (atakujacy znajduje hash w rainbow table) Z sola: "password" + random_salt → inny hash (rainbow table przestaje byc uzyteczne)

2. Brute Force Attack

Atak polega na sprawdzaniu kazdej mozliwej kombinacji znakow az do znalezienia poprawnego hasla.

Cechy:

Obrona:


3. Dictionary Attack

Atakujacy testuje liste najpopularniejszych hasel oraz slow ze slownika. Jest znacznie szybszy niz brute force.

Przyklady hasel latwych do zlamania:

Obrona:


4. Credential Stuffing

Wykorzystuje dane wyciekle z innych serwisow. Atakujacy automatycznie probuje kombinacji email + haslo na wielu stronach.

Dlaczego jest skuteczny?

Obrona:


5. Password Spraying

Zamiast probowac wielu hasel dla jednego konta, atakujacy probuje jednego popularnego hasla dla wielu kont.

Cel: ominiecie blokad konta.

Obrona:


6. GPU / Hardware Attack

Wykorzystuje karty graficzne lub specjalizowany sprzet (ASIC), aby liczyc miliony hashy na sekunde.

Obrona:


7. Phishing

Atak socjotechniczny – uzytkownik sam podaje haslo na falszywej stronie przypominajacej prawdziwy serwis.

Obrona:


Najwazniejsza zasada bezpieczenstwa

NIGDY nie przechowuj hasel w plain text. Zawsze: haslo → salt → wolny hash (Argon2/bcrypt)

Co warto powiedziec na rozmowie?

56. Co to jest sol (salt) i pieprz (pepper) w haszowaniu?

🎯 Podstawy:
Koncept Opis Przechowywanie
Salt (sol) Losowy ciag dodawany do hasla przed haszowaniem, unikalny dla kazdego hasla Razem z hashem w bazie
Pepper (pieprz) Staly sekret dodawany do wszystkich hasel W konfiguracji/env, NIE w bazie
Bez soli (ZLE): "password" --> SHA256 --> "5e884898..." (zawsze to samo!) Rainbow table attack mozliwy Z sola (DOBRZE): "password" + "random_salt_123" --> SHA256 --> "a1b2c3d4..." "password" + "other_salt_456" --> SHA256 --> "x9y8z7w6..." (inny hash!) Rainbow table bezuzyteczny Bcrypt automatycznie generuje i przechowuje sol: $2a$12$LQv3c1yqBWVHxkd0LHAkCO... ^^^^ ^^ ^^^^^^^^^^^^^^^^^^^^^^ algo cost sol + hash

56b. Wyciek bazy danych i jak się przed nim chronić

Wyciek bazy danych (data breach) to sytuacja, w której nieuprawniona osoba uzyskuje dostęp do danych przechowywanych w systemie, np. użytkowników, haseł, tokenów, numerów kart czy danych osobowych.

Najważniejsze: Zakłada się, że wyciek kiedyś nastąpi. Dlatego system projektuje się tak, aby skradzione dane były bezużyteczne.

Jak dochodzi do wycieku?

1. SQL Injection

Atakujący wstrzykuje zapytanie SQL przez formularz lub API.

// Złe (SQL injection możliwy)
SELECT * FROM users WHERE email = '" + email + "' AND password = '" + password + "';

// Dobre (parametryzowane zapytania)
userRepository.findByEmail(email);

✅ ORM i parametryzowane zapytania eliminują SQL Injection.

2. Skradzione dane dostępowe

Obrona: Vault / AWS Secret Manager / GCP Secret Manager, rotacja kluczy, zasada least privilege.

3. Błędna konfiguracja chmury

✅ DB powinna być dostępna tylko z prywatnej sieci (VPC).

4. Exploit podatności

✅ Regularne aktualizacje, skanery zależności (Snyk, Dependabot).

5. Malware / przejęcie serwera

Co jeśli baza wycieknie?

Najważniejsze pytanie: Czy atakujący może użyć tych danych?

Jak REALNIE zabezpiecza się backend?

1. Hashowanie haseł

Absolutny MUST: Argon2 + salt + wysoki cost.

2. Szyfrowanie danych wrażliwych

PESEL, numer karty, adres → użycie encryption at rest, np. AES-256.

3. Zasada minimalnych uprawnień

Aplikacja nie powinna mieć uprawnień: SUPERUSER, DROP TABLE, ALTER DATABASE, tylko SELECT/INSERT/UPDATE.

4. Segmentacja sieci

Internet
   ↓
Load Balancer
   ↓
Backend
   ↓
Private Network
   ↓
Database

✅ Baza nigdy nie powinna być publiczna.

5. Backupy + plan incydentu
6. Monitoring i alerty

Stack: Prometheus, Grafana, SIEM

Ataki offline

Największe ryzyko: ktoś kradnie bazę i łamie hasła lokalnie. ✅ Dlatego szybkie hashe (SHA256) są złe, wolne (Argon2) są dobre.

Podsumowanie do rozmowy kwalifikacyjnej:

System projektuję tak, jakby wyciek bazy był nieunikniony. Hasła haszuję Argon2 z salt, dane wrażliwe szyfruję, stosuję least privilege i izoluję bazę w prywatnej sieci. Dzięki temu nawet w przypadku breach attacker nie może łatwo wykorzystać danych.

57. Jakie sa rodzaje szyfrowania?

🎯 Podstawy:

Szyfrowanie symetryczne (ten sam klucz):

Algorytm Opis Uzycie
AES-256 Standard, bardzo bezpieczny Szyfrowanie danych, dyskow, baz
ChaCha20 Szybki, bezpieczny, dobry na mobile TLS, VPN

Szyfrowanie asymetryczne (klucz publiczny + prywatny):

Algorytm Opis Uzycie
RSA Klasyczny, klucze 2048-4096 bit Podpisy JWT, wymiana kluczy, TLS
ECDSA Krotsze klucze, szybszy JWT, certyfikaty, blockchain
Ed25519 Nowoczesny, bardzo szybki SSH, podpisy
Symetryczne: Klucz: "secret123" Alice --[AES + klucz]--> zaszyfrowane --[AES + klucz]--> Bob ENCRYPT DECRYPT Problem: jak bezpiecznie przekazac klucz? Asymetryczne: Bob ma: klucz publiczny (udostepniony) + klucz prywatny (tajny) Alice --[RSA + Bob public key]--> zaszyfrowane --[RSA + Bob private key]--> Bob ENCRYPT DECRYPT Tylko Bob moze odszyfrowac (ma prywatny klucz)

SOLID

🎬 Materiały wideo (PL):

58. Czym sa zasady SOLID?

🎯 Podstawy:

SOLID - 5 zasad projektowania obiektowego, ktore prowadza do czytelnego, elastycznego i latwo testowalnego kodu.

Litera Zasada Opis
S Single Responsibility Klasa powinna mieć tylko jedną odpowiedzialność i tylko jeden powód do zmiany. Pojedyncza klasa nie powinna pełnić wielu ról jednocześnie, bo wtedy staje się trudna w utrzymaniu, testowaniu i rozwoju.
O Open/Closed Klasy powinny być otwarte na rozszerzenia, ale zamknięte na modyfikacje. Nową funkcjonalność dodajemy przez rozszerzenie (np. dziedziczenie, wzorce projektowe), a nie przez modyfikację istniejącego kodu.
L Liskov Substitution Obiekty klasy bazowej powinny być wymienialne z obiektami klasy pochodnej bez wpływu na poprawność działania programu. Podklasa nie powinna łamać zachowania oczekiwanego od klasy bazowej (np. jeśli Ptak ma metodę fly(), to Pingwin nie powinien dziedziczyć po Ptak, bo nie lata).
I Interface Segregation Zamiast jednego dużego interfejsu należy definiować wiele mniejszych, specyficznych interfejsów. Klasy implementują tylko te metody, które są dla nich rzeczywiście potrzebne - kod staje się bardziej modularny i łatwiejszy do testowania.
D Dependency Inversion Klasa powinna zależeć od interfejsu, nie od konkretnej klasy. Np. UserService powinien przyjmować UserRepository jako interfejs, a nie MySQLUserRepository - dzięki temu łatwo podmienisz bazę danych na inną lub użyjesz mocka w testach.

59. Single Responsibility Principle (SRP) - przyklad

🎯 Podstawy:

Zasada: Klasa powinna mieć tylko jedną odpowiedzialność i tylko jeden powód do zmiany. Pojedyncza klasa nie powinna pełnić wielu ról jednocześnie, ponieważ wtedy staje się trudna w utrzymaniu, testowaniu i rozwoju.

// ZLE - klasa ma wiele odpowiedzialnosci
public class UserService {
    public void createUser(User user) { /* ... */ }
    public void sendWelcomeEmail(User user) { /* ... */ }
    public String generateReport(List<User> users) { /* ... */ }
    public void exportToPdf(String report) { /* ... */ }
}

// DOBRZE - kazda klasa ma jedna odpowiedzialnosc
public class UserService {
    public void createUser(User user) { /* ... */ }
}

public class EmailService {
    public void sendWelcomeEmail(User user) { /* ... */ }
}

public class UserReportGenerator {
    public String generateReport(List<User> users) { /* ... */ }
}

public class PdfExporter {
    public void export(String content) { /* ... */ }
}

60. Open/Closed Principle (OCP) - przyklad

🎯 Podstawy:

Zasada: Oprogramowanie (klasy, moduły) powinno być otwarte na rozszerzenia, ale zamknięte na modyfikacje. Nową funkcjonalność dodajemy poprzez rozszerzenie (np. przez dziedziczenie lub wzorce projektowe), a nie przez bezpośrednią modyfikację istniejących klas.

// ZLE - trzeba modyfikowac klase przy kazdym nowym typie
public class DiscountCalculator {
    public BigDecimal calculate(Order order) {
        if (order.getCustomerType() == CustomerType.REGULAR) {
            return order.getTotal().multiply(new BigDecimal("0.05"));
        } else if (order.getCustomerType() == CustomerType.VIP) {
            return order.getTotal().multiply(new BigDecimal("0.15"));
        }
        // Dodanie nowego typu wymaga modyfikacji tej klasy!
        return BigDecimal.ZERO;
    }
}

// DOBRZE - rozszerzamy przez nowe implementacje
public interface DiscountStrategy {
    BigDecimal calculate(Order order);
}

public class RegularDiscount implements DiscountStrategy {
    public BigDecimal calculate(Order order) {
        return order.getTotal().multiply(new BigDecimal("0.05"));
    }
}

public class VipDiscount implements DiscountStrategy {
    public BigDecimal calculate(Order order) {
        return order.getTotal().multiply(new BigDecimal("0.15"));
    }
}

// Dodanie nowego typu = nowa klasa, BEZ modyfikacji istniejacych
public class BlackFridayDiscount implements DiscountStrategy {
    public BigDecimal calculate(Order order) {
        return order.getTotal().multiply(new BigDecimal("0.30"));
    }
}

61. Liskov Substitution Principle (LSP) - przyklad

🎯 Podstawy:

Zasada: Obiekty klasy bazowej powinny być wymienialne z obiektami klasy pochodnej bez wpływu na poprawność działania programu. Podklasa nie powinna łamać zachowania oczekiwanego od klasy bazowej.

// ZLE - lamie LSP (kwadrat nie jest prostokatem w sensie zachowania)
public class Rectangle {
    protected int width, height;

    public void setWidth(int w) { width = w; }
    public void setHeight(int h) { height = h; }
    public int getArea() { return width * height; }
}

public class Square extends Rectangle {
    @Override
    public void setWidth(int w) { width = height = w; }
    @Override
    public void setHeight(int h) { width = height = h; }
}

// Problem:
Rectangle rect = new Square();
rect.setWidth(5);
rect.setHeight(10);
rect.getArea(); // Oczekujemy 50, dostajemy 100! Zlamana zasada.

// DOBRZE - oddzielne klasy lub wspolny interfejs
public interface Shape {
    int getArea();
}

public class Rectangle implements Shape {
    private final int width, height;
    public Rectangle(int w, int h) { width = w; height = h; }
    public int getArea() { return width * height; }
}

public class Square implements Shape {
    private final int side;
    public Square(int s) { side = s; }
    public int getArea() { return side * side; }
}

62. Interface Segregation Principle (ISP) - przyklad

🎯 Podstawy:

Zasada: Zamiast jednego dużego interfejsu powinno się definiować wiele mniejszych, specyficznych interfejsów, tak aby klasy implementowały tylko te metody, które są dla nich rzeczywiście potrzebne. Dzięki temu kod staje się bardziej modularny i łatwiejszy do testowania.

// ZLE - jeden duzy interfejs
public interface Worker {
    void work();
    void eat();
    void sleep();
    void code();
    void attendMeeting();
}

// Robot nie je ani nie spi - musi implementowac puste metody
public class Robot implements Worker {
    public void work() { /* ok */ }
    public void eat() { /* nie dotyczy! */ }
    public void sleep() { /* nie dotyczy! */ }
    public void code() { /* ok */ }
    public void attendMeeting() { /* nie dotyczy! */ }
}

// DOBRZE - wiele malych interfejsow
public interface Workable {
    void work();
}

public interface Eatable {
    void eat();
}

public interface Sleepable {
    void sleep();
}

public interface Programmer extends Workable {
    void code();
}

// Robot implementuje tylko to co potrzebuje
public class Robot implements Workable, Programmer {
    public void work() { /* ... */ }
    public void code() { /* ... */ }
}

// Czlowiek implementuje wiecej
public class Human implements Workable, Eatable, Sleepable, Programmer {
    /* wszystkie metody */
}

63. Dependency Inversion Principle (DIP) - przyklad

🎯 Podstawy:

Zasada: Moduły wysokiego poziomu nie powinny zależeć od modułów niskiego poziomu. Oba powinny zależeć od abstrakcji (np. interfejsów), a nie od konkretnych implementacji. Prowadzi to do słabego sprzężenia i większej elastyczności kodu.

// ZLE - bezposrednia zaleznosc od konkretnej implementacji
public class OrderService {
    private MySqlOrderRepository repository = new MySqlOrderRepository();
    private SmtpEmailSender emailSender = new SmtpEmailSender();

    public void createOrder(Order order) {
        repository.save(order);
        emailSender.send(order.getCustomerEmail(), "Order created");
    }
}
// Nie mozna latwo zmienic bazy ani sposobu wysylania maili
// Nie mozna testowac bez prawdziwej bazy i serwera SMTP

// DOBRZE - zaleznosc od abstrakcji (interfejsow)
public interface OrderRepository {
    void save(Order order);
}

public interface NotificationService {
    void notify(String recipient, String message);
}

@Service
public class OrderService {
    private final OrderRepository repository;
    private final NotificationService notificationService;

    // Dependency Injection przez konstruktor
    public OrderService(OrderRepository repository,
                        NotificationService notificationService) {
        this.repository = repository;
        this.notificationService = notificationService;
    }

    public void createOrder(Order order) {
        repository.save(order);
        notificationService.notify(order.getCustomerEmail(), "Order created");
    }
}

// Mozna latwo podmienic implementacje:
// - MySqlOrderRepository, MongoOrderRepository, InMemoryOrderRepository
// - SmtpEmailSender, SmsNotification, MockNotification (w testach)

Model Richardsona (REST Maturity Model)

🎬 Materiały wideo (PL):

64. Co to jest Model Dojrzalosci Richardsona?

🎯 Podstawy:

Richardson Maturity Model - model opisujacy poziomy dojrzalosci API RESTowego. Stworzony przez Leonarda Richardsona.

Poziom Nazwa Opis Przyklad
0 The Swamp of POX Jeden URL, jedna metoda (POST), wszystko w body POST /api z akcja w JSON
1 Resources Rozne URLe dla roznych zasobow POST /users, POST /orders
2 HTTP Verbs Poprawne uzycie metod HTTP GET/POST/PUT/DELETE /users
3 Hypermedia (HATEOAS) Odpowiedzi zawieraja linki do powiazanych akcji JSON z _links

65. Poziom 0 - The Swamp of POX

🎯 Podstawy:

Jedno URL jako tunel dla wszystkich operacji. Praktycznie RPC over HTTP.

// Wszystko przez jeden endpoint
POST /api/service HTTP/1.1
Content-Type: application/json

{
  "action": "getUser",
  "userId": 123
}

POST /api/service HTTP/1.1
{
  "action": "createOrder",
  "customerId": 456,
  "products": [...]
}

POST /api/service HTTP/1.1
{
  "action": "deleteUser",
  "userId": 123
}
Problemy: Brak wykorzystania HTTP, trudne cachowanie, brak standardow

66. Poziom 1 - Resources

🎯 Podstawy:

Rozne URLe dla roznych zasobow, ale nadal jedna metoda (zazwyczaj POST).

// Osobne endpointy dla zasobow
POST /users/get
{
  "userId": 123
}

POST /users/create
{
  "name": "Jan",
  "email": "jan@example.com"
}

POST /orders/create
{
  "customerId": 456,
  "products": [...]
}
Poprawa: Logiczny podzial na zasoby, ale nadal nie wykorzystuje HTTP

67. Poziom 2 - HTTP Verbs

🎯 Podstawy:

Poprawne uzycie metod HTTP i kodow statusu. To jest standard dla wiekszosc API REST.

// Pobieranie
GET /users/123
// Response: 200 OK + dane uzytkownika

// Tworzenie
POST /users
{ "name": "Jan", "email": "jan@example.com" }
// Response: 201 Created + Location: /users/123

// Aktualizacja
PUT /users/123
{ "name": "Jan Nowak", "email": "jan@example.com" }
// Response: 200 OK

// Usuniecie
DELETE /users/123
// Response: 204 No Content

// Bledy
GET /users/999
// Response: 404 Not Found

POST /users
{ "email": "invalid" }
// Response: 400 Bad Request
Poziom 2 jest wystarczajacy dla wiekszosc aplikacji!

68. Poziom 3 - HATEOAS (Hypermedia)

🎯 Podstawy:

HATEOAS (Hypermedia as the Engine of Application State) - odpowiedzi zawieraja linki do mozliwych akcji.

GET /orders/123

{
  "id": 123,
  "status": "PENDING",
  "total": 299.99,
  "customer": {
    "id": 456,
    "name": "Jan Kowalski"
  },
  "_links": {
    "self": {
      "href": "/orders/123"
    },
    "customer": {
      "href": "/customers/456"
    },
    "cancel": {
      "href": "/orders/123/cancel",
      "method": "POST"
    },
    "pay": {
      "href": "/orders/123/payment",
      "method": "POST"
    },
    "items": {
      "href": "/orders/123/items"
    }
  }
}

// Po oplaceniu zamowienia - inne dostepne akcje
GET /orders/123

{
  "id": 123,
  "status": "PAID",
  "_links": {
    "self": { "href": "/orders/123" },
    "ship": { "href": "/orders/123/ship", "method": "POST" },
    "refund": { "href": "/orders/123/refund", "method": "POST" }
    // "cancel" i "pay" juz niedostepne!
  }
}
// Spring HATEOAS
@GetMapping("/orders/{id}")
public EntityModel<Order> getOrder(@PathVariable Long id) {
    Order order = orderService.findById(id);

    EntityModel<Order> model = EntityModel.of(order);

    model.add(linkTo(methodOn(OrderController.class).getOrder(id)).withSelfRel());
    model.add(linkTo(methodOn(CustomerController.class).getCustomer(order.getCustomerId())).withRel("customer"));

    if (order.getStatus() == Status.PENDING) {
        model.add(linkTo(methodOn(OrderController.class).cancelOrder(id)).withRel("cancel"));
        model.add(linkTo(methodOn(PaymentController.class).pay(id)).withRel("pay"));
    }

    return model;
}
Zalety HATEOAS: Klient nie musi znac wszystkich URL, API jest samoopisujace, latwe dodawanie nowych akcji
W praktyce: Poziom 3 rzadko stosowany, wiekszosc API zatrzymuje sie na poziomie 2

Programowanie Obiektowe (OOP)

🎬 Materiały wideo (PL):

69. Jakie sa 4 filary programowania obiektowego?

🎯 Podstawy:
Filar Opis Slowo kluczowe
Enkapsulacja Ukrywanie wewnetrznej implementacji, dostep przez metody private, gettery/settery
Abstrakcja Pokazywanie tylko istotnych cech, ukrywanie szczegulow abstract, interface
Dziedziczenie Tworzenie nowych klas na bazie istniejacych extends, implements
Polimorfizm Jeden interfejs, wiele implementacji @Override, przeciazanie

70. Co to jest enkapsulacja i dlaczego jest wazna?

🎯 Podstawy:

Enkapsulacja - ukrywanie wewnetrznego stanu obiektu i udostepnianie kontrolowanego dostepu przez metody.

// ZLE - publiczne pola, brak kontroli
public class BankAccount {
    public BigDecimal balance;  // kazdy moze zmienic!
}

BankAccount account = new BankAccount();
account.balance = new BigDecimal("-1000"); // ujemne saldo?!

// DOBRZE - prywatne pola, kontrola przez metody
public class BankAccount {
    private BigDecimal balance;

    public BankAccount(BigDecimal initialBalance) {
        if (initialBalance.compareTo(BigDecimal.ZERO) < 0) {
            throw new IllegalArgumentException("Initial balance cannot be negative");
        }
        this.balance = initialBalance;
    }

    public BigDecimal getBalance() {
        return balance;  // tylko odczyt
    }

    public void deposit(BigDecimal amount) {
        if (amount.compareTo(BigDecimal.ZERO) <= 0) {
            throw new IllegalArgumentException("Amount must be positive");
        }
        balance = balance.add(amount);
    }

    public void withdraw(BigDecimal amount) {
        if (amount.compareTo(balance) > 0) {
            throw new InsufficientFundsException("Not enough balance");
        }
        balance = balance.subtract(amount);
    }
}
Zalety: Walidacja danych, kontrola dostepu, mozliwosc zmiany implementacji bez wplywu na klientow

71. Co to jest abstrakcja?

🎯 Podstawy:

Abstrakcja - pokazywanie tylko istotnych cech, ukrywanie szczegulow implementacji.

// Abstrakcja - definiuje CO ma byc zrobione, nie JAK
public interface PaymentProcessor {
    PaymentResult processPayment(PaymentRequest request);
}

// Uzytkownik nie musi znac szczegulow implementacji
public class OrderService {
    private final PaymentProcessor paymentProcessor;

    public void checkout(Order order) {
        // Nie wiem czy to Stripe, PayPal czy przelew - i nie musza wiedziec!
        PaymentResult result = paymentProcessor.processPayment(
            new PaymentRequest(order.getTotal())
        );
    }
}

// Rozne implementacje - ukryte szczegoly
public class StripePaymentProcessor implements PaymentProcessor {
    public PaymentResult processPayment(PaymentRequest request) {
        // Cala logika Stripe API tutaj
    }
}

public class PayPalPaymentProcessor implements PaymentProcessor {
    public PaymentResult processPayment(PaymentRequest request) {
        // Cala logika PayPal API tutaj
    }
}

72. Co to jest dziedziczenie i kiedy je stosowac?

🎯 Podstawy:

Dziedziczenie - mechanizm pozwalajacy klasie przejac pola i metody innej klasy.

// Klasa bazowa
public abstract class Vehicle {
    protected String brand;
    protected int year;

    public void start() {
        System.out.println("Vehicle starting...");
    }

    public abstract void move();  // musi byc zaimplementowana
}

// Klasy pochodne
public class Car extends Vehicle {
    private int numberOfDoors;

    @Override
    public void move() {
        System.out.println("Car driving on road");
    }
}

public class Boat extends Vehicle {
    @Override
    public void move() {
        System.out.println("Boat sailing on water");
    }
}
Kiedy stosowac: Relacja "jest" (Car IS A Vehicle). Wspolny kod w klasie bazowej.
Preferuj kompozycje nad dziedziczenie! Dziedziczenie tworzy silne powiazanie.

73. Co to jest polimorfizm?

🎯 Podstawy:

Polimorfizm - mozliwosc traktowania obiektow roznych klas przez wspolny interfejs.

// Polimorfizm - rozne zachowanie, jeden interfejs
public interface NotificationSender {
    void send(String recipient, String message);
}

public class EmailSender implements NotificationSender {
    public void send(String recipient, String message) {
        System.out.println("Sending EMAIL to " + recipient);
    }
}

public class SmsSender implements NotificationSender {
    public void send(String recipient, String message) {
        System.out.println("Sending SMS to " + recipient);
    }
}

public class PushSender implements NotificationSender {
    public void send(String recipient, String message) {
        System.out.println("Sending PUSH to " + recipient);
    }
}

// Polimorficzne uzycie - kod nie zalezy od konkretnej implementacji
public class NotificationService {
    private final List<NotificationSender> senders;

    public void notifyAll(String recipient, String message) {
        for (NotificationSender sender : senders) {
            sender.send(recipient, message);  // rozne zachowanie!
        }
    }
}

// Typy polimorfizmu:
// 1. Compile-time (przeciazanie metod - overloading)
public void print(String s) { }
public void print(int i) { }
public void print(String s, int count) { }

// 2. Runtime (nadpisywanie metod - overriding)
NotificationSender sender = new EmailSender();  // lub SmsSender
sender.send("user@email.com", "Hello");  // wywolanie zalezne od typu obiektu

74. Czym rozni sie kompozycja od dziedziczenia?

🎯 Podstawy:
Cecha Dziedziczenie Kompozycja
Relacja "jest" (IS-A) "ma" (HAS-A)
Powiazanie Silne (compile-time) Luźne (runtime)
Elastycznosc Mniejsza Wieksza
Testowanie Trudniejsze Latwiejsze (mozna mockowac)
Slowo kluczowe extends Pole w klasie
// DZIEDZICZENIE - Car IS A Vehicle
public class Car extends Vehicle {
    // dziedziczy wszystko z Vehicle
}

// KOMPOZYCJA - Car HAS AN Engine (preferowane!)
public class Car {
    private final Engine engine;        // HAS-A
    private final Transmission transmission;
    private final List<Wheel> wheels;

    public Car(Engine engine, Transmission transmission) {
        this.engine = engine;
        this.transmission = transmission;
    }

    public void start() {
        engine.start();  // delegacja do komponentu
    }
}

// Zalety kompozycji:
// - Mozna latwo podmienic Engine (ElectricEngine, DieselEngine)
// - Latwiejsze testowanie (mock Engine)
// - Brak problemow z hierarchia klas
Zasada: "Favor composition over inheritance" - preferuj kompozycje nad dziedziczenie

75. Co to jest klasa, obiekt i instancja?

🎯 Podstawy:
Pojecie Opis Analogia
Klasa Szablon/blueprint definiujacy strukture i zachowanie Przepis na ciasto
Obiekt Konkretny egzemplarz klasy w pamieci Upieczone ciasto
Instancja Synonim obiektu - utworzony egzemplarz klasy To samo upieczone ciasto
// Klasa - szablon
public class User {
    private String name;
    private String email;

    public User(String name, String email) {
        this.name = name;
        this.email = email;
    }
}

// Obiekty/Instancje - konkretne egzemplarze
User user1 = new User("Jan", "jan@email.com");   // pierwsza instancja
User user2 = new User("Anna", "anna@email.com"); // druga instancja

// Kazdy obiekt ma wlasny stan (dane) ale wspoldzieli zachowanie (metody)

76. Czym roznia sie metody i pola statyczne od instancyjnych?

🎯 Podstawy:
Cecha Statyczne (static) Instancyjne
Przynaleznosc Do klasy Do obiektu
Pamiec Jedna kopia dla wszystkich Osobna dla kazdego obiektu
Dostep ClassName.method() object.method()
Dostep do this NIE TAK
Uzycie Utility, stale, fabryki Stan i zachowanie obiektu
public class Counter {
    // Pole statyczne - wspolne dla wszystkich instancji
    private static int totalCount = 0;

    // Pole instancyjne - osobne dla kazdego obiektu
    private int instanceCount = 0;

    public Counter() {
        totalCount++;      // wspolny licznik
        instanceCount++;   // licznik tej instancji
    }

    // Metoda statyczna - dostep bez tworzenia obiektu
    public static int getTotalCount() {
        return totalCount;
    }

    // Metoda instancyjna - wymaga obiektu
    public int getInstanceCount() {
        return instanceCount;
    }
}

// Uzycie
Counter c1 = new Counter();
Counter c2 = new Counter();

Counter.getTotalCount();  // 2 (statyczna - bez obiektu)
c1.getInstanceCount();   // 1 (instancyjna - z obiektem)

Concurrency - Deadlock i pokrewne problemy

🎬 Materiały wideo (PL):

77. Co to jest Deadlock?

🎯 Podstawy:

Deadlock (zakleszczenie) - sytuacja, w ktorej dwa lub wiecej watkow/procesow czeka na siebie nawzajem, blokujac sie wzajemnie na zawsze.

DEADLOCK - klasyczny przyklad: Watek A: Watek B: 1. Zablokuj zasob X ──────┐ ┌─── 1. Zablokuj zasob Y 2. Czekaj na zasob Y ◄────┼──┼─── 2. Czekaj na zasob X ▲ │ │ ▲ └────────────────┴──┴──────────────┘ OBAJ CZEKAJA W NIESKONCZONOSC

4 warunki Coffmana (wszystkie musza byc spelnione):

  1. Mutual Exclusion - zasob moze byc uzywany tylko przez jeden watek
  2. Hold and Wait - watek trzyma zasob i czeka na kolejny
  3. No Preemption - zasobu nie mozna odebrac sila
  4. Circular Wait - cykliczne czekanie (A→B→C→A)

Deadlock w Java (przyklad):

public class DeadlockExample {
    private final Object lockA = new Object();
    private final Object lockB = new Object();

    public void method1() {
        synchronized(lockA) {           // 1. Zablokuj A
            synchronized(lockB) {       // 2. Czekaj na B
                // praca
            }
        }
    }

    public void method2() {
        synchronized(lockB) {           // 1. Zablokuj B
            synchronized(lockA) {       // 2. Czekaj na A  DEADLOCK!
                // praca
            }
        }
    }
}

Rozwiazanie - ustalona kolejnosc blokad:

// ZAWSZE blokuj w tej samej kolejnosci: A przed B
public void method1() {
    synchronized(lockA) {
        synchronized(lockB) { /* praca */ }
    }
}

public void method2() {
    synchronized(lockA) {           // Zmieniona kolejnosc!
        synchronized(lockB) { /* praca */ }
    }
}

78. Deadlock w bazach danych

🎯 Podstawy:

Bazy danych automatycznie wykrywaja deadlocki i przerywaja jedna z transakcji.

Transakcja 1: Transakcja 2: UPDATE users SET ... WHERE id=1 UPDATE orders SET ... WHERE id=100 (blokada na users id=1) (blokada na orders id=100) │ │ ▼ ▼ UPDATE orders SET ... WHERE id=100 UPDATE users SET ... WHERE id=1 (czeka na orders id=100) (czeka na users id=1) │ │ └──────────── DEADLOCK ──────────────┘ Baza danych: Rollback jednej transakcji, rzuca wyjatek
-- Jak zapobiegac deadlockom w SQL:
-- 1. Ustalona kolejnosc dostępu do tabel (np. alfabetyczna)
-- 2. Krotkie transakcje (mniej czasu na konflikt)
-- 3. Niski poziom izolacji jesli mozliwe
-- 4. SELECT ... FOR UPDATE NOWAIT (nie czekaj, rzuc blad)

SELECT * FROM users WHERE id = 1 FOR UPDATE NOWAIT;
-- Jesli zablokowane, natychmiast rzuci wyjatek zamiast czekac

Strategie radzenia sobie z deadlockami:

1. Zapobieganie (Prevention) - projektuj system tak, aby unikac deadlockow:

Technika Opis Przyklad
Kolejnosc zasobow Zawsze zadaj zasobow w ustalonej kolejnosci Najpierw Account, potem Order (alfabetycznie)
Timeout Przerwij transakcje po przekroczeniu czasu oczekiwania lock_timeout = 5s
Wywlaszczenie (Preemption) System odbiera lock i cofa transakcje Baza automatycznie wybiera "ofiare"
Krotkie transakcje Im krotsza transakcja, tym mniejsze ryzyko Unikaj dlugotrwalych operacji w transakcji
// Java/JPA - ustalona kolejnosc zasobow
// ZAWSZE najpierw blokuj Account, potem Order (np. alfabetycznie)
@Transactional
public void transferMoney(Long accId, Long orderId) {
    // 1. Najpierw Account
    Account acc = em.find(Account.class, accId, LockModeType.PESSIMISTIC_WRITE);
    // 2. Potem Order
    Order ord = em.find(Order.class, orderId, LockModeType.PESSIMISTIC_WRITE);
    // ... operacje
}

// Timeout na poziomie JPA
@QueryHints({
    @QueryHint(name = "javax.persistence.lock.timeout", value = "5000")  // 5 sekund
})
Account findByIdWithLock(Long id);

2. Wykrywanie i rozwiazywanie (Detection & Resolution) - pozwol na deadlocki, ale wykrywaj i rozwiazuj:

Diagnostyka locków w PostgreSQL (terminal):

# 1. Połączenie z bazą danych przez terminal
psql -h localhost -p 5434 -U product_user -d product

# Parametry połączenia:
#   -h localhost    = host bazy danych
#   -p 5434         = port (domyślny PostgreSQL to 5432)
#   -U product_user = nazwa użytkownika
#   -d product      = nazwa bazy danych

# Po połączeniu możesz wykonywać zapytania SQL:
-- 2. Wszystkie aktywne locki w systemie
SELECT * FROM pg_locks;

-- 3. Sprawdzenie które procesy są zablokowane i przez kogo
SELECT
    pid,
    usename,
    pg_blocking_pids(pid) AS blocked_by,
    query
FROM pg_stat_activity
WHERE cardinality(pg_blocking_pids(pid)) > 0;

-- 4. Szczegółowe informacje o lockach z zapytaniami
SELECT
    l.locktype,
    l.relation::regclass,
    l.mode,
    l.granted,
    a.usename,
    a.query
FROM pg_locks l
JOIN pg_stat_activity a ON l.pid = a.pid
WHERE l.relation IS NOT NULL;

-- 5. Ustawienie timeout na poziomie sesji (zapobieganie długim oczekiwaniom)
SET lock_timeout = '5s';
SET statement_timeout = '30s';

-- 6. Zabicie zablokowanego procesu (ostrożnie!)
SELECT pg_terminate_backend(pid);  -- gdzie pid = ID procesu do zabicia

3. Obsluga deadlocka w kodzie Java:

@Service
public class OrderService {

    private static final int MAX_RETRIES = 3;

    @Transactional
    public void processOrder(Long orderId) {
        int attempt = 0;
        while (attempt < MAX_RETRIES) {
            try {
                doProcessOrder(orderId);
                return;  // Sukces - wyjdz z petli
            } catch (PessimisticLockingFailureException | CannotAcquireLockException e) {
                attempt++;
                log.warn("Deadlock detected, retry {}/{}", attempt, MAX_RETRIES);
                if (attempt >= MAX_RETRIES) {
                    throw new BusinessException("Failed after " + MAX_RETRIES + " retries");
                }
                // Losowe opoznienie przed ponowna proba (unikniecie livelock)
                Thread.sleep((long) (Math.random() * 100));
            }
        }
    }
}

79. Livelock vs Starvation vs Race Condition

🎯 Podstawy:
Problem Opis Przyklad
Deadlock Watki zablokowane na zawsze, NIC nie robia A czeka na B, B czeka na A
Livelock Watki ciagle reaguja na siebie, ale nie robia postepu Dwoch ludzi w korytarzu - obaj ustepuja w te sama strone
Starvation Watek nigdy nie dostaje zasobu (inni go "wyprzedzaja") Watek niskiego priorytetu nigdy nie dostaje CPU
Race Condition Wynik zalezy od kolejnosci wykonania watkow Dwa watki inkrementuja counter bez synchronizacji

Race Condition - przyklad:

// PROBLEM: Race condition
private int counter = 0;

public void increment() {
    counter++;  // NIE jest atomowe! (read → modify → write)
}

// ROZWIAZANIE 1: synchronized
public synchronized void increment() {
    counter++;
}

// ROZWIAZANIE 2: AtomicInteger (lepsze)
private AtomicInteger counter = new AtomicInteger(0);

public void increment() {
    counter.incrementAndGet();  // Atomowa operacja
}

Livelock - przyklad:

// Dwoch "uprzejmych" watkow - obaj ustepuja i nikt nie przechodzi
while (otherThreadWantsResource) {
    releaseResource();           // "Prosze, idz pierwszy"
    Thread.sleep(100);
    acquireResource();           // "Dobra, teraz ja... o, znowu chcesz?"
}
// Oba watki ciagle zwalniaja i pobieraja - zadnego postepu

// ROZWIAZANIE: Losowe opoznienie (jak w Ethernet CSMA/CD)
Thread.sleep(new Random().nextInt(100));

80. Jak zapobiegac problemom wspolbieznosci?

🎯 Podstawy:
Technika Opis Kiedy uzywac
synchronized Blokada na poziomie metody/bloku Proste przypadki, maly kod krytyczny
ReentrantLock Jawna blokada z tryLock(), timeout Potrzeba timeout lub fairness
Atomic* AtomicInteger, AtomicReference (CAS) Pojedyncze zmienne, wysokia wydajnosc
volatile Zapewnia widocznosc zmian miedzy watkami Flagi (np. isRunning), pojedyncze odczyty/zapisy
Immutability Niemutowalne obiekty sa thread-safe Najlepsza praktyka - unikaj stanu mutowalnego
ThreadLocal Kazdy watek ma wlasna kopie Kontekst per-thread (np. user session)
Concurrent Collections ConcurrentHashMap, CopyOnWriteArrayList Wspoldzielone kolekcje

ReentrantLock z timeout (zapobiega deadlock):

private final ReentrantLock lock = new ReentrantLock();

public void safeMethod() {
    try {
        // Probuj zdobyc blokade przez max 1 sekunde
        if (lock.tryLock(1, TimeUnit.SECONDS)) {
            try {
                // sekcja krytyczna
            } finally {
                lock.unlock();
            }
        } else {
            // Nie udalo sie zdobyc blokady - obsluz inaczej
            log.warn("Could not acquire lock, skipping operation");
        }
    } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
    }
}

81. Optimistic vs Pessimistic Locking

🎯 Podstawy:

Optimistic i Pessimistic Locking to strategie zarzadzania wspolbieznym dostepem do danych w transakcjach.

Cecha Optimistic Locking Pessimistic Locking
Zalozenie Konflikty sa rzadkie Konflikty sa czeste
Mechanizm Wersjonowanie (@Version) Blokada rekordu (SELECT FOR UPDATE)
Kiedy sprawdza Przy COMMIT (czy wersja sie zgadza) Przy odczycie (blokuje od razu)
Wydajnosc Lepsza przy malej liczbie konfliktow Lepsza przy duzej liczbie konfliktow
Deadlock Nie wystepuje Moze wystapic
Kiedy uzywac Odczyty >> Zapisy, aplikacje webowe Krytyczne operacje finansowe, rezerwacje

Optimistic Locking

Pozwala na wykonywanie transakcji bez ograniczen, sprawdzajac konflikty dopiero przed zatwierdzeniem. W przypadku wykrycia konfliktu transakcja jest wycofywana.

Java (JPA @Version):

@Entity
public class Counter {
    @Id
    private Long id;

    private int value;

    @Version  // Automatycznie inkrementowane przy UPDATE
    private Long version;
}

// Uzycie w serwisie
@Transactional
public void incrementCounter(Long id) {
    Counter counter = counterRepository.findById(id).orElseThrow();
    counter.setValue(counter.getValue() + 1);
    counterRepository.save(counter);  // Hibernate sprawdzi version przy COMMIT
}

// Obsluga konfliktu
try {
    incrementCounter(1L);
} catch (OptimisticLockException e) {
    // Konflikt! Ktos inny zmodyfikowal rekord - ponow probe lub poinformuj uzytkownika
    log.warn("Optimistic lock conflict, retrying...");
}

SQL (co generuje Hibernate):

-- Odczyt rekordu (bez blokady)
SELECT id, value, version FROM counter WHERE id = 1;
-- Wynik: id=1, value=10, version=5

-- UPDATE z warunkiem na version
UPDATE counter
SET value = 11, version = 6
WHERE id = 1 AND version = 5;

-- Jesli affected_rows = 0 → ktos inny zmienil rekord → OptimisticLockException
-- Jesli affected_rows = 1 → sukces
OPTIMISTIC LOCKING - SCENARIUSZ KONFLIKTU: Czas Transakcja A Transakcja B ───────────────────────────────────────────────────────────── t1 SELECT (version=5) t2 SELECT (version=5) t3 UPDATE ... WHERE version=5 (sukces, version→6) t4 UPDATE ... WHERE version=5 (FAIL! version juz = 6) → OptimisticLockException

Pessimistic Locking

Blokuje zasoby potrzebne transakcji od razu przy odczycie, uniemozliwiajac innym dostep do nich do czasu zwolnienia blokady. Zapobiega to konfliktom, ale moze zmniejszyc wspolbieznosc i prowadzic do deadlockow.

SQL (SELECT FOR UPDATE):

-- Blokada wiersza - inne transakcje czekaja
SELECT * FROM counter WHERE id = 1 FOR UPDATE;

-- Warianty:
SELECT ... FOR UPDATE NOWAIT;       -- Nie czekaj, rzuc blad jesli zablokowane
SELECT ... FOR UPDATE SKIP LOCKED; -- Pomin zablokowane wiersze

-- Po SELECT FOR UPDATE mozna bezpiecznie UPDATE
UPDATE counter SET value = value + 1 WHERE id = 1;
COMMIT;  -- Blokada zwolniona

Java (EntityManager):

// Sposob 1: EntityManager.find() z LockModeType
@Transactional
public void incrementCounterPessimistic(Long id) {
    Counter counter = entityManager.find(
        Counter.class,
        id,
        LockModeType.PESSIMISTIC_WRITE  // SELECT ... FOR UPDATE
    );
    counter.setValue(counter.getValue() + 1);
    // Blokada trzymana do COMMIT
}

// Sposob 2: Repository z @Lock
public interface CounterRepository extends JpaRepository<Counter, Long> {

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query("SELECT c FROM Counter c WHERE c.id = :id")
    Counter findByIdWithLock(@Param("id") Long id);
}

// Sposob 3: Z timeout (unikniecie nieskonczonego czekania)
Map<String, Object> hints = new HashMap<>();
hints.put("javax.persistence.lock.timeout", 5000);  // 5 sekund

Counter counter = entityManager.find(
    Counter.class, id,
    LockModeType.PESSIMISTIC_WRITE,
    hints
);
PESSIMISTIC LOCKING - SCENARIUSZ: Czas Transakcja A Transakcja B ───────────────────────────────────────────────────────────── t1 SELECT ... FOR UPDATE (blokada na wiersz id=1) t2 SELECT ... FOR UPDATE (CZEKA... blokada zajeta) t3 UPDATE value = 11 t4 COMMIT (blokada zwolniona) t5 (dostaje blokade) UPDATE value = 12 t6 COMMIT

LockModeType w JPA:

LockModeType SQL Opis
PESSIMISTIC_READ FOR SHARE Shared lock - inne moga czytac, nie moga pisac
PESSIMISTIC_WRITE FOR UPDATE Exclusive lock - nikt inny nie ma dostepu
PESSIMISTIC_FORCE_INCREMENT FOR UPDATE + version++ Exclusive lock + inkrementacja wersji
OPTIMISTIC - Sprawdza version przy COMMIT
OPTIMISTIC_FORCE_INCREMENT - Zawsze inkrementuje version przy COMMIT

Dodatkowe pojęcia

🎬 Materiały wideo (PL):

82. Agregacja i Kompozycja (OOP)

🎯 Podstawy:

Agregacja i Kompozycja to relacje "has-a" w programowaniu obiektowym, różniące się siłą powiązania.

Cecha Agregacja Kompozycja
Relacja Luźna ("has-a") Silna ("owns-a")
Cykl życia Obiekt może istnieć niezależnie Obiekt nie istnieje bez właściciela
Przykład Uniwersytet → Studenci Samochód → Silnik
// AGREGACJA - Student istnieje niezależnie od Uniwersytetu
public class University {
    private List<Student> students;  // studenci mogą istnieć bez uniwersytetu

    public void addStudent(Student student) {
        students.add(student);  // student stworzony na zewnątrz
    }
}

// KOMPOZYCJA - Silnik nie istnieje bez Samochodu
public class Car {
    private final Engine engine;

    public Car() {
        this.engine = new Engine();  // silnik tworzony wewnątrz, umiera z samochodem
    }
}

Agregacja danych w mikroserwisach:

Łączenie danych z wielu serwisów w jedną odpowiedź.

// API Gateway agreguje dane z wielu serwisów
@GetMapping("/dashboard/{userId}")
public DashboardResponse getDashboard(@PathVariable Long userId) {
    User user = userService.getUser(userId);
    List<Order> orders = orderService.getOrders(userId);
    PaymentSummary payments = paymentService.getSummary(userId);

    return new DashboardResponse(user, orders, payments);  // agregacja
}

83. Propagacja (kontekstu, błędów, transakcji)

🎯 Podstawy:

Propagacja oznacza przekazywanie informacji między warstwami lub komponentami systemu.

Typ propagacji Opis Przykład
Propagacja transakcji Jak transakcja zachowuje się przy wywołaniu innej metody REQUIRED, REQUIRES_NEW, NESTED
Propagacja kontekstu Przekazywanie security context, traceId między serwisami JWT token, correlation ID w nagłówkach
Propagacja błędów Jak wyjątki przechodzą między warstwami Exception → HTTP 500
// Propagacja błędów - wyjątek domenowy → HTTP response
@Service
public class OrderService {
    public void createOrder(Order order) {
        if (order.getTotal().compareTo(BigDecimal.ZERO) <= 0) {
            throw new InvalidOrderException("Total must be positive");
        }
    }
}

@RestControllerAdvice
public class GlobalExceptionHandler {
    @ExceptionHandler(InvalidOrderException.class)
    public ResponseEntity<ErrorResponse> handleInvalidOrder(InvalidOrderException e) {
        return ResponseEntity.badRequest().body(new ErrorResponse(e.getMessage()));
    }
}

84. Deterministyczność

🎯 Podstawy:

System deterministyczny - dla tych samych danych wejściowych zawsze daje ten sam wynik. Brak losowości i efektów ubocznych.

Deterministyczne Niedeterministyczne
Funkcje czyste (pure functions) Zależne od czasu (LocalDateTime.now())
Haszowanie (ten sam input → ten sam hash) Zależne od losowości (Random)
Sortowanie stabilne Zależne od kolejności wątków
// DETERMINISTYCZNA - zawsze ten sam wynik dla tych samych argumentów
public int add(int a, int b) {
    return a + b;
}

// NIEDETERMINISTYCZNA - wynik zależy od czasu
public String generateId() {
    return UUID.randomUUID().toString();  // losowy wynik
}

// Jak uczynić kod deterministycznym w testach:
public class OrderService {
    private final Clock clock;  // wstrzykujemy zegar

    public Order createOrder() {
        return new Order(LocalDateTime.now(clock));  // deterministyczne w testach
    }
}

85. Deserializacja

🎯 Podstawy:

Deserializacja - proces zamiany danych z formatu tekstowego/binarnego (JSON, XML) na obiekty w pamięci.

Kierunek Nazwa Przykład
Obiekt → JSON/XML Serializacja User → {"name": "Jan"}
JSON/XML → Obiekt Deserializacja {"name": "Jan"} → User
// Jackson - deserializacja JSON → Object
ObjectMapper mapper = new ObjectMapper();

// Deserializacja
String json = "{\"name\": \"Jan\", \"age\": 30}";
User user = mapper.readValue(json, User.class);

// Serializacja
String jsonOutput = mapper.writeValueAsString(user);

// Spring automatycznie deserializuje body requestu
@PostMapping("/users")
public User createUser(@RequestBody User user) {  // JSON → User
    return userService.save(user);
}

Ryzyka bezpieczeństwa:

86. @RequestParam vs @PathVariable vs @QueryParam

🎯 Podstawy:

Adnotacje służące do pobierania parametrów z żądania HTTP.

Adnotacja Źródło Przykład URL Framework
@PathVariable Ścieżka URL /users/123 Spring
@RequestParam Query string (?key=value) /users?age=30 Spring
@QueryParam Query string /users?age=30 JAX-RS
// Spring - @PathVariable i @RequestParam
@GetMapping("/users/{id}")
public User getUser(
    @PathVariable Long id,                         // /users/123
    @RequestParam(required = false) String fields  // ?fields=name,email
) { ... }

// Paginacja i sortowanie
@GetMapping("/products")
public List<Product> getProducts(
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "10") int size,
    @RequestParam(defaultValue = "name") String sortBy
) { ... }

// JAX-RS - @QueryParam
@GET
@Path("/users")
public List<User> getUsers(@QueryParam("age") int age) { ... }

87. Tokenowanie

🎯 Podstawy:

Tokenowanie - zamiana danych wrażliwych na token (losowy identyfikator). Token sam w sobie nie zawiera danych.

Cecha Tokenowanie Szyfrowanie Haszowanie
Dane Przechowywane w bezpiecznym storage Zamienione matematycznie Zamienione jednokierunkowo na skrót (hash)
Odwracalność Tylko przez lookup w bazie tokenów Przez klucz deszyfrujący Nieodwracalne (one-way function)
Token Losowy, bez związku z danymi Matematycznie powiązany z danymi Deterministyczny - te same dane = ten sam hash
// Tokenowanie numeru karty płatniczej
@Service
public class TokenizationService {

    private final TokenRepository tokenRepository;

    public String tokenize(String cardNumber) {
        String token = UUID.randomUUID().toString();
        tokenRepository.save(new TokenMapping(token, encrypt(cardNumber)));
        return token;  // "tok_abc123" zamiast "4111111111111111"
    }

    public String detokenize(String token) {
        return tokenRepository.findByToken(token)
            .map(m -> decrypt(m.getEncryptedData()))
            .orElseThrow();
    }
}

Zastosowania: płatności (PCI DSS), dane osobowe (RODO), sesje użytkowników

88. DNS (Domain Name System)

🎯 Podstawy:

DNS - system tłumaczący nazwy domenowe na adresy IP.

Przeglądarka → DNS Resolver → Root DNS → TLD DNS (.com) → Authoritative DNS ↓ example.com → 93.184.216.34
Typ rekordu Opis Przykład
A IPv4 address example.com → 93.184.216.34
AAAA IPv6 address example.com → 2606:2800:220:1:...
CNAME Alias do innej domeny www.example.com → example.com
MX Mail server example.com → mail.example.com

Znaczenie w architekturze:

89. Prefix URL i wersjonowanie API

🎯 Podstawy:

Prefix - wspólny początek ścieżki URL dla grupy endpointów.

// Prefix na poziomie kontrolera
@RestController
@RequestMapping("/api/v1/users")  // prefix: /api/v1/users
public class UserController {

    @GetMapping          // GET /api/v1/users
    public List<User> getAll() { ... }

    @GetMapping("/{id}") // GET /api/v1/users/123
    public User getById(@PathVariable Long id) { ... }
}

// Globalny prefix w application.yml
server:
  servlet:
    context-path: /api

Strategie wersjonowania API:

Strategia Przykład Zalety/Wady
URL path /api/v1/users Proste, czytelne
Query param /api/users?version=1 Elastyczne, ale mniej RESTful
Header X-API-Version: 1 Czyste URL, trudniejsze testowanie

90. Nexus i Gitea

🎯 Podstawy:

Nexus Repository Manager

Nexus - repozytorium artefaktów używane w CI/CD.

<!-- Maven - publikacja do Nexusa -->
<distributionManagement>
    <repository>
        <id>nexus-releases</id>
        <url>http://nexus.company.com/repository/maven-releases/</url>
    </repository>
</distributionManagement>

Gitea

Gitea - self-hosted Git server, lżejsza alternatywa dla GitHub/GitLab.

91. Jenkins Pipeline

🎯 Podstawy:

Jenkins Pipeline - narzędzie CI/CD z pipeline'em jako kodem (Jenkinsfile).

// Jenkinsfile - Declarative Pipeline
pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'mvn clean compile'
            }
        }
        stage('Test') {
            steps {
                sh 'mvn test'
            }
            post {
                always {
                    junit '**/target/surefire-reports/*.xml'
                }
            }
        }
        stage('Security Scan') {
            steps {
                sh 'mvn dependency-check:check'
            }
        }
        stage('Deploy') {
            when {
                branch 'main'
            }
            steps {
                sh 'kubectl apply -f k8s/'
            }
        }
    }
    post {
        failure {
            mail to: 'team@company.com', subject: 'Build Failed'
        }
    }
}

92. Argo CD i GitOps

🎯 Podstawy:

GitOps

GitOps - podejście, w którym Git jest jedynym źródłem prawdy dla infrastruktury i aplikacji.

Argo CD

Argo CD - narzędzie do continuous deployment na Kubernetes, implementujące GitOps.

Developer → Git Push → GitHub/GitLab ↓ Argo CD (obserwuje repo) ↓ Kubernetes Cluster (synchronizuje stan)
# ArgoCD Application manifest
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/company/my-app.git
    targetRevision: HEAD
    path: k8s/
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true      # usuń zasoby nieobecne w Git
      selfHeal: true   # napraw drift automatycznie

93. WildFly / JBoss

🎯 Podstawy:

WildFly (dawniej JBoss AS) - serwer aplikacyjny Java EE / Jakarta EE.

Cecha WildFly Spring Boot
Typ Serwer aplikacyjny (full) Embedded server (Tomcat)
Specyfikacja Jakarta EE (EJB, CDI, JPA, JTA) Spring Framework
Deployment WAR/EAR na serwer Executable JAR
Wersja enterprise JBoss EAP (Red Hat) Spring Enterprise

Funkcje serwera aplikacyjnego:

94. RabbitMQ vs Kafka

🎯 Podstawy:

Dwa popularne systemy do komunikacji asynchronicznej między serwisami.

Kafka vs RabbitMQ - porównanie architektury
Cecha RabbitMQ Kafka
Model Message broker (kolejki) Event streaming platform (log)
Przechowywanie Usuwa po konsumpcji Przechowuje przez określony czas
Konsumenci Competing consumers Consumer groups + replay
Routing Exchange + routing keys Partycje + klucze
Skalowalność Dobra Bardzo wysoka (miliony msg/s)
Kiedy używać Task queues, RPC, krótkie wiadomości Event sourcing, duże strumienie danych, analityka
// Spring - RabbitMQ Producer
@Service
public class OrderProducer {
    private final RabbitTemplate rabbitTemplate;

    public void sendOrder(Order order) {
        rabbitTemplate.convertAndSend("orders-exchange", "order.created", order);
    }
}

// RabbitMQ Consumer
@RabbitListener(queues = "orders-queue")
public void handleOrder(Order order) {
    orderService.process(order);
}

// Spring - Kafka Producer
@Service
public class EventProducer {
    private final KafkaTemplate<String, OrderEvent> kafkaTemplate;

    public void publishEvent(OrderEvent event) {
        kafkaTemplate.send("order-events", event.getOrderId(), event);
    }
}

// Kafka Consumer
@KafkaListener(topics = "order-events", groupId = "inventory-service")
public void handleEvent(OrderEvent event) {
    inventoryService.updateStock(event);
}
RabbitMQ: Kafka: Producer → Exchange → Queue → Consumer Producer → Topic → Partition → Consumer Group ↓ ↓ Routing Key Offset (replay) (usuwa po ACK) (przechowuje N dni)

Sieć i Infrastruktura

🎬 Materiały wideo (PL):

93. DNS (Domain Name System)

🎯 Podstawy:

DNS to system tłumaczący nazwy domenowe (np. google.com) na adresy IP. Działa jak "książka telefoniczna internetu".

Typ rekordu Opis Przykład
A Mapuje domenę na adres IPv4 example.com → 93.184.216.34
AAAA Mapuje domenę na adres IPv6 example.com → 2606:2800:220:1:...
CNAME Alias - wskazuje na inną domenę www.example.com → example.com
MX Serwer poczty dla domeny example.com → mail.example.com
TXT Dowolny tekst (weryfikacja, SPF) Weryfikacja własności domeny
NS Serwery nazw dla domeny ns1.cloudflare.com
Proces rozwiązywania DNS: Przeglądarka → Cache lokalny → Resolver ISP → Root Server (.com) → TLD Server → Authoritative NS ↑ ↓ └──────────────────────────── IP Address ←─────────────────────────────────────┘ TTL (Time To Live) = jak długo cache'ować odpowiedź (np. 3600s = 1h)
Praktyczne zastosowania:

94. Proxy - Forward Proxy vs Reverse Proxy

🎯 Podstawy:

Proxy to serwer pośredniczący między klientem a serwerem docelowym.

Cecha Forward Proxy Reverse Proxy
Pozycja Przed klientem Przed serwerem
Kto wie o proxy Klient (musi skonfigurować) Serwer ukryty, klient nie wie
Zastosowanie Anonimowość, filtrowanie, cache Load balancing, SSL, ochrona
Przykłady VPN, Squid, proxy firmowe Nginx, HAProxy, Cloudflare
FORWARD PROXY: REVERSE PROXY: Klient ──→ [Forward Proxy] ──→ Internet Internet ──→ [Reverse Proxy] ──→ Serwer ↓ (klient wie o proxy) (klient nie wie, że istnieje backend) ├──→ Server 1 ├──→ Server 2 └──→ Server 3

95. Nginx

🎯 Podstawy:

Nginx (wymowa: "engine-x") to wysokowydajny serwer HTTP i reverse proxy. Znany z obsługi ogromnej liczby jednoczesnych połączeń przy minimalnym zużyciu pamięci.

Funkcja Opis
Web Server Serwowanie plików statycznych (HTML, CSS, JS, obrazy)
Reverse Proxy Przekazywanie requestów do serwerów backendowych
Load Balancer Rozkładanie ruchu między wieloma instancjami (round-robin, least_conn, ip_hash)
SSL Termination Obsługa HTTPS - backend może używać HTTP
Cache Cachowanie odpowiedzi, zmniejszenie obciążenia backendu
Rate Limiting Ograniczanie liczby requestów (ochrona przed DDoS)
Kompresja Gzip/Brotli - zmniejszenie transferu danych
# Przykład konfiguracji Nginx jako reverse proxy
upstream backend {
    server localhost:8080;
    server localhost:8081;
    server localhost:8082;
}

server {
    listen 80;
    server_name api.example.com;

    # Redirect HTTP → HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name api.example.com;

    ssl_certificate     /etc/ssl/cert.pem;
    ssl_certificate_key /etc/ssl/key.pem;

    # Kompresja
    gzip on;
    gzip_types application/json text/plain;

    # Rate limiting
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

    location /api/ {
        limit_req zone=api burst=20;
        proxy_pass http://backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    # Pliki statyczne
    location / {
        root /var/www/html;
        try_files $uri $uri/ /index.html;
    }
}
Architektura z Nginx: ┌─────────────────────────────────────┐ Internet ──→ DNS ──→│ NGINX │ │ • SSL Termination │ │ • Rate Limiting │ │ • Compression │ │ • Load Balancing │ └───────────┬─────────────────────────┘ │ ┌─────────────────┼─────────────────┐ ↓ ↓ ↓ [App Server 1] [App Server 2] [App Server 3] :8080 :8081 :8082

96. Ngrok

🎯 Podstawy:

Ngrok (wymowa: "en-grok") to narzędzie do tworzenia tuneli HTTP/TCP, które wystawia lokalny serwer na świat przez publiczny URL. Idealne do developmentu i testowania webhooków.

Zastosowanie Opis
Testowanie webhooków Stripe, GitHub, Slack mogą wysyłać eventy na localhost
Prezentacje Pokazanie lokalnej aplikacji klientowi bez deploymentu
Mobile testing Testowanie API z telefonu bez konfiguracji sieci
Debugging Inspekcja ruchu HTTP w dashboardzie ngrok
# Uruchomienie ngrok - eksponuje port 8080
$ ngrok http 8080

# Wynik:
Forwarding   https://a1b2c3d4.ngrok.io → http://localhost:8080

# Teraz https://a1b2c3d4.ngrok.io jest dostępne z internetu!

# Przydatne opcje:
$ ngrok http 8080 --domain=my-app.ngrok.io  # stała subdomena (płatne)
$ ngrok http 8080 --basic-auth="user:pass"  # podstawowa autoryzacja
$ ngrok tcp 3306                            # tunel TCP (np. baza danych)
Jak działa Ngrok: ┌──────────────┐ ┌──────────────────┐ ┌─────────────────┐ │ Webhook │ ───→ │ Ngrok Cloud │ ───→ │ Ngrok Client │ ───→ localhost:8080 │ (Stripe) │ │ (publiczny IP) │ │ (Twój komputer)│ └──────────────┘ └──────────────────┘ └─────────────────┘ URL: https://abc123.ngrok.io/webhook/stripe
Uwaga: Ngrok tworzy tunel przez ich serwery - nie używaj do wrażliwych danych produkcyjnych. Darmowa wersja generuje losowe URL przy każdym uruchomieniu.

97. Cloudflare

🎯 Podstawy:

Cloudflare to globalna sieć CDN i usług bezpieczeństwa. Działa jako reverse proxy między użytkownikami a Twoim serwerem.

Usługa Opis
CDN (Content Delivery Network) Cache statycznych zasobów na 300+ serwerach na świecie - szybsze ładowanie
DDoS Protection Ochrona przed atakami - Cloudflare absorbuje złośliwy ruch
WAF (Web Application Firewall) Blokowanie SQL Injection, XSS, i innych ataków
SSL/TLS Darmowy certyfikat HTTPS, automatyczne odnowienie
DNS Szybki i niezawodny DNS z ochroną przed atakami
Workers Serverless functions na edge (blisko użytkownika)
Rate Limiting Ograniczanie requestów z danego IP
Bot Protection CAPTCHA, challenge dla podejrzanego ruchu
Architektura z Cloudflare: Cloudflare Edge (300+ lokalizacji) Użytkownik ──→ DNS ──→ Cloudflare ─────────────────────→ Origin Server (Polska) (Frankfurt) │ (Twój serwer) │ ┌───────────┴───────────┐ │ • DDoS mitigation │ │ • WAF rules │ │ • Cache (CDN) │ │ • SSL termination │ │ • Compression │ └───────────────────────┘ Cache HIT: Cloudflare odpowiada bez kontaktu z origin (szybko!) Cache MISS: Request przechodzi do origin server
// Cloudflare Workers - kod na edge
addEventListener('fetch', event => {
    event.respondWith(handleRequest(event.request));
});

async function handleRequest(request) {
    // Dodaj custom header
    const response = await fetch(request);
    const newResponse = new Response(response.body, response);
    newResponse.headers.set('X-Custom-Header', 'Hello from Edge!');
    return newResponse;
}
Porównanie narzędzi:

98. Typowa architektura produkcyjna

🎯 Podstawy:

Jak te technologie współpracują w realnym systemie:

┌─────────────────────────────────────────────────────────────────────────────────┐ │ INTERNET │ └───────────────────────────────────┬─────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────────────────────────────┐ │ DNS (Cloudflare DNS) │ │ api.example.com → Cloudflare IP │ └───────────────────────────────────┬─────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────────────────────────────┐ │ CLOUDFLARE (CDN + WAF) │ │ • DDoS protection • SSL • Cache • WAF │ └───────────────────────────────────┬─────────────────────────────────────────────┘ │ ↓ ┌─────────────────────────────────────────────────────────────────────────────────┐ │ NGINX (Load Balancer) │ │ • SSL termination • Rate limiting • Routing │ └───────────────────────────────────┬─────────────────────────────────────────────┘ │ ┌─────────────────────┼─────────────────────┐ ↓ ↓ ↓ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ order-service │ │ payment-service │ │ product-service │ │ :8080 │ │ :8081 │ │ :8082 │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ └─────────────────────┼─────────────────────┘ ↓ ┌─────────────────┐ │ Database │ │ PostgreSQL │ └─────────────────┘

99. Model OSI (Open Systems Interconnection)

Model OSI to teoretyczny model referencyjny opisujący komunikację sieciową w postaci 7 warstw. Każda warstwa świadczy usługi warstwie wyższej i korzysta z usług warstwy niższej. Został opracowany przez ISO w 1984 r. jako standard opisu sieci komputerowych.

🎯 Podstawy, które musisz znać

Po co w ogóle powstał model OSI?

Żeby producenci sprzętu i twórcy oprogramowania mogli pracować niezależnie. Bez wspólnego modelu Ethernet od jednej firmy nie rozmawiałby z kablem od innej, a przeglądarka nie wiedziałaby jak dogadać się z serwerem. OSI dzieli komunikację na warstwy, żeby każdy robił swoje.

🔑 Główne założenia modelu OSI

  1. Rozdzielenie odpowiedzialności (separation of concerns) - każda warstwa robi jedną rzecz i nic więcej. Warstwa transportowa nie interesuje się kablami, a warstwa fizyczna nie wie co to HTTP.
  2. Warstwa wyższa korzysta z warstwy niższej - HTTP (L7) korzysta z TCP (L4), TCP z IP (L3), IP z Ethernet (L2). Jak klocki Lego.
  3. Każda warstwa dokłada swój nagłówek (enkapsulacja). Odbiorca zdejmuje nagłówki po kolei - jak odpakowywanie prezentu warstwa po warstwie.
  4. Warstwa nie widzi co robią inne - możesz wymienić Wi-Fi na Ethernet, a HTTP dalej działa. To dlatego internet jest tak elastyczny.

🧩 Kluczowe cechy, które odróżniają warstwy

💡 Najważniejsze rzeczy do zapamiętania

# Warstwa Funkcja Jednostka danych (PDU) Protokoły / przykłady
7 Aplikacji (Application) Interfejs dla aplikacji użytkownika, udostępnianie usług sieciowych Dane (Data) HTTP, HTTPS, FTP, SMTP, DNS, SSH, IMAP, POP3
6 Prezentacji (Presentation) Kodowanie, szyfrowanie, kompresja i konwersja formatów danych Dane (Data) TLS/SSL, JPEG, PNG, ASCII, UTF-8, MIME
5 Sesji (Session) Nawiązywanie, utrzymywanie i kończenie sesji między aplikacjami Dane (Data) NetBIOS, RPC, PPTP, SOCKS
4 Transportowa (Transport) Niezawodny transport end-to-end, kontrola przepływu, segmentacja, kontrola błędów Segment (TCP) / Datagram (UDP) TCP, UDP, QUIC
3 Sieciowa (Network) Routing pakietów między sieciami, logiczne adresowanie (IP) Pakiet (Packet) IP (IPv4/IPv6), ICMP, routery, protokoły routingu (OSPF, BGP)
2 Łącza danych (Data Link) Przesył ramek w jednej sieci lokalnej, adresy fizyczne MAC, detekcja błędów Ramka (Frame) Ethernet, Wi-Fi (802.11), ARP, switche, MAC
1 Fizyczna (Physical) Przesył surowych bitów przez medium transmisyjne (elektryczne, optyczne, radiowe) Bit Kable miedziane, światłowody, radio, huby, RJ-45, napięcia, sygnały
Mnemotechnika (od góry): All People Seem To Need Data Processing (Application, Presentation, Session, Transport, Network, Data Link, Physical).
Od dołu: Please Do Not Throw Sausage Pizza Away.

Enkapsulacja danych - jak dane przechodzą przez warstwy

Nadawca: dane z warstwy wyższej są pakowane (enkapsulacja) i uzupełniane o nagłówek każdej kolejnej warstwy w dół. Odbiorca wykonuje proces odwrotny (dekapsulacja) - każda warstwa zdejmuje swój nagłówek i przekazuje dane wyżej.

Nadawca                           Odbiorca
L7 Application   [Data]              [Data]           L7
L6 Presentation  [Data]              [Data]           L6
L5 Session       [Data]              [Data]           L5
L4 Transport     [TCP|Data]          [TCP|Data]       L4
L3 Network       [IP|TCP|Data]       [IP|TCP|Data]    L3
L2 Data Link     [Eth|IP|TCP|Data|FCS] [Eth|...]      L2
L1 Physical      010110100101...  →  010110100101... L1

OSI vs TCP/IP

Model OSI (7 warstw) Model TCP/IP (4 warstwy)
Aplikacji + Prezentacji + Sesji Aplikacji (HTTP, DNS, SMTP)
Transportowa Transportowa (TCP, UDP)
Sieciowa Internetowa (IP, ICMP)
Łącza danych + Fizyczna Dostępu do sieci (Ethernet, Wi-Fi)

Na jakiej warstwie pracują typowe urządzenia i protokoły?

Po co znać OSI w pracy backendu?
Uwaga: OSI to model teoretyczny - w praktyce internet działa na modelu TCP/IP. Warstwy 5-7 w OSI często łączy się w jedną warstwę aplikacji (tak jak w TCP/IP).

100. Mapa ataków: atak → warstwa OSI → mechanizm → obrona

Cel mapy: pokazać gdzie w systemie (na której warstwie) dany atak się odbywa, jak działa i czym się bronić. Tak myślą architekci sieci i specjaliści bezpieczeństwa - operacyjnie, nie tylko teoretycznie.

🎯 Podstawy, które musisz znać

Po co mapować ataki na warstwy OSI?

Bo gdzie atak się odbywa, tam trzeba go blokować. Nie zatrzymasz SQL Injection firewallem sieciowym (bo SQLi jest na L7), tak jak nie zatrzymasz SYN Flood walidacją formularza (bo to atak na L4). Mapa mówi ci: "problem jest tu, więc obrona musi być tu".

🔑 Główne założenia myślenia o bezpieczeństwie

  1. Triada CIA - każdy atak łamie jedną z trzech rzeczy:
    • Confidentiality (poufność) - np. podsłuch, kradzież danych
    • Integrity (integralność) - np. modyfikacja danych, MITM
    • Availability (dostępność) - np. DDoS, ransomware
  2. Defense in Depth - nie ma jednej magicznej ochrony. Buduj warstwy: firewall + TLS + MFA + WAF + monitoring. Jak jedna zawiedzie, następna łapie atak.
  3. Zero Trust - nie ufaj nikomu, nawet w sieci wewnętrznej. Każde żądanie musi się uwierzytelnić i autoryzować.
  4. Least Privilege - każdy (użytkownik, proces, serwis) ma tylko minimalne uprawnienia potrzebne do pracy. Jak coś zostanie zhakowane, szkody są ograniczone.

🧩 Jak rozpoznać, na której warstwie jest atak

💡 Najważniejsze rzeczy do zapamiętania

🧱 Warstwa 1 — Fizyczna

Rzadziej omawiana, ale nadal realna - wymaga dostępu fizycznego.

Atak Mechanizm Jak działa Obrona
Physical Tampering Fizyczny dostęp do sprzętu Atakujący podłącza się do kabla, wyjmuje dysk, instaluje sniffer sprzętowy (np. Komputer → Kabel → Sniffer) Kontrola dostępu do pomieszczeń, monitoring, szyfrowanie dysków, zamykane szafy rack

🔗 Warstwa 2 — Łącza danych

Ataki w sieciach lokalnych (LAN) - dotyczą adresów MAC i switchy.

Atak Mechanizm Jak działa Obrona
ARP Spoofing Fałszywe mapowanie IP → MAC Atakujący wysyła rozgłoszenie: "Router ma MAC: AA:BB:CC" zamiast prawdziwego "DD:EE:FF" → ruch trafia do atakującego (MITM w LAN) ARP inspection (DAI), statyczne wpisy ARP, segmentacja VLAN, HTTPS (szyfrowanie nawet w razie MITM)
MAC Flooding Przepełnienie tablicy MAC w switchu Atak wysyła tysiące fałszywych adresów MAC → switch zaczyna działać jak hub (broadcast wszystkiego) → podsłuch ruchu Port security, ograniczenie liczby MAC na port

🌍 Warstwa 3 — Sieciowa

Tu dzieje się routing i adresowanie IP.

Atak Mechanizm Jak działa Obrona
IP Spoofing Podszywanie się pod inny IP Pakiet wygląda jak From: 192.168.1.1, ale naprawdę pochodzi z From: attacker Ingress filtering (BCP38), firewall, analiza ruchu, uwierzytelnianie na wyższych warstwach
ICMP Flood Zalewanie pakietami ICMP Ogromna liczba pingów (ping ping ping...) → serwer nie nadąża z odpowiadaniem Rate limiting ICMP, firewall (blokada/limit ICMP), scrubbing DDoS

🚚 Warstwa 4 — Transportowa

TCP i UDP - porty, sesje, handshake.

Atak Mechanizm Jak działa Obrona
SYN Flood Niepełne połączenia TCP Normalny handshake: SYN → SYN-ACK → ACK. Atak: SYN → SYN-ACK → brak ACK → serwer trzyma otwarte sesje → wyczerpanie zasobów SYN cookies, firewall, load balancer, limity połączeń półotwartych
Port Scanning Sprawdzanie otwartych portów Atakujący testuje porty (22, 80, 443, 3306...) szukając otwartych usług i ich wersji Firewall (domyślnie DROP), zamknięte porty, IDS/IPS (np. Snort, Suricata), port knocking

🧵 Warstwy 5–7 — Sesja / Prezentacja / Aplikacja

Tu dzieje się większość nowoczesnych ataków.

Atak Warstwa Mechanizm Jak działa Obrona
MITM (Man in the Middle) 2–7 Przejęcie komunikacji Ty → Atakujący → Serwer (atakujący czyta/modyfikuje ruch) HTTPS, certyfikaty TLS, HSTS, certificate pinning, VPN firmowy
Phishing 7 Manipulacja użytkownikiem Fałszywy mail: "Kliknij tutaj → login" → strona kradnie hasło MFA, szkolenia użytkowników, filtry antyspamowe, SPF/DKIM/DMARC
SQL Injection 7 Manipulacja zapytaniami SQL Input ' OR 1=1 -- zmienia logikę zapytania SQL Prepared statements (parametryzacja), walidacja danych, ORM, least privilege na DB, WAF
XSS (Cross-Site Scripting) 7 Wstrzyknięcie JavaScript Kod <script>stealCookies()</script> wykonuje się w przeglądarce ofiary Escape'owanie outputu, CSP (Content Security Policy), HttpOnly cookies, walidacja inputu
CSRF 7 Wykonanie akcji w imieniu użytkownika Strona atakującego wysyła transferMoney() z ciasteczkami zalogowanego użytkownika CSRF tokens, SameSite cookies, sprawdzanie Referer/Origin, ponowne uwierzytelnienie
Malware / Trojan Wszystkie Instalacja złośliwego oprogramowania Program VPN.exe działa, ale instaluje backdoor Antywirus/EDR, whitelist aplikacji, aktualizacje, sandboxing
Ransomware Wszystkie Szyfrowanie plików Program szyfruje dane → żąda okupu za klucz Backup offline (3-2-1), segmentacja sieci, EDR, ograniczenie uprawnień, testowanie odtworzeń
Supply Chain Attack 7 Zainfekowana aktualizacja / zależność Legalny program/biblioteka zawiera ukryty malware (np. SolarWinds, event-stream npm) Weryfikacja podpisów, kontrola zależności (SCA), SBOM, pinowanie wersji, audyt aktualizacji
DDoS 3–7 Przeciążenie systemu Typy: UDP flood (L4), HTTP flood (L7), DNS amplification (L7 amplified), Slowloris (L7) Rate limiting, CDN (Cloudflare, Akamai), load balancing, WAF, auto-scaling, scrubbing center

🧠 Meta-wnioski

1. Najwięcej ataków dzieje się na warstwie 7 (aplikacji).
Nie w kablach, nie w routerach - w aplikacjach. Stąd tak ważne są walidacja inputu, testy bezpieczeństwa i code review.

2. Najlepszą obroną jest warstwowość (Defense in Depth).
Nie pojedyncze zabezpieczenie, tylko kombinacja:
Firewall + TLS + MFA + Monitoring + WAF + Least privilege
Każda warstwa łapie to, co przepuściła poprzednia.

3. Najsłabszym elementem jest użytkownik.
Najczęstsze wektory to phishing, malware i błędna konfiguracja - nie sprzęt ani protokoły. Stąd MFA, szkolenia i zasada najmniejszych uprawnień.

Kolejny krok (poziom SOC / DevSecOps): mapa atak → objawy w systemie → jak go wykryć (logi, metryki, anomalie). To pozwala nie tylko bronić się, ale też wykrywać trwające incydenty.

Wygenerowano przez Claude AI