Skip to content

Bezpečnost – Public API a Middleware

Veřejné Endpointy (Public API)

Veřejné endpointy jsou určeny pro JavaScript frontend a prochází middleware pipelinem s bezpečnostními kontrolami.

Registrace Public Endpointu

Public endpointy se registrují v config/data.yaml:

# config/data.yaml
publicEndpoints:
  - CookiesBar/updateLog
  - Form/submit
  - Newsletter/subscribe

Pouze endpointy v tomto whitelist projdou middleware. Všechny ostatní vrátí 403.

Bezpečnostní Kontroly

Middleware v app/Middlewares/Restriction/publicEndpointsMiddleware.php kontroluje:

  1. Whitelist firewall - Pouze endpointy v config/data.yaml jsou povoleny
  2. CSRF token - Povinný (csrf query param nebo POST)
  3. Rate limiting - Max 20 requestů za 60 sekund na IP
  4. Referer check - Validace origin (volitelná)

Všechny pokusy o přístup jsou logovány do var/log/security.log.

Volání Public Endpointu

// 1. Příprava CSRF tokenu
const csrfToken = document.querySelector('[data-csrf]').dataset.csrf;

// 2. POST na public endpoint s CSRF
fetch('/getData/CookiesBar/updateLog?csrf=' + encodeURIComponent(csrfToken), {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ oldToken: 'value' })
})
.then(response => response.json())
.then(data => console.log('Success:', data))
.catch(error => {
    if (error.status === 403) {
        console.error('CSRF token invalid or rate limit exceeded');
    }
});

CSRF Ochrana

CSRF token musí být součástí každého veřejného requestu:

// CSRF z data atributu v HTML
<div data-csrf="<?= Session::get('frontend_csrf') ?>"></div>

// JS
const csrfToken = document.querySelector('[data-csrf]').dataset.csrf;
fetch('/getData/CookiesBar/updateLog?csrf=' + encodeURIComponent(csrfToken));

Nebo jako POST data:

fetch('/getData/CookiesBar/updateLog', {
    method: 'POST',
    body: JSON.stringify({ csrf: csrfToken, data: '...' })
});

Rate Limiting

Public endpointy jsou chráněny rate limitingem:

  • Max: 20 requestů
  • Per: 60 sekund
  • Per IP: Individuální limit pro každou IP adresu

Pokud limit překročíte, vrátí 429 Too Many Requests.

// Příliš rychlé requesty = 429
for (let i = 0; i < 25; i++) {
    fetch('/getData/CookiesBar/updateLog?csrf=...');
}
// Posledních 5 requestů = 429 Too Many Requests

IP Filtrování a CORS

Přístup je kontrolován dle nastavení v .env:

ALLOWED_IP=127.0.0.1,::1,93.185.102.4
CORS_ORIGINS=
  • ALLOWED_IP - IPs povolené pro cron/admin-only endpointy
  • CORS_ORIGINS - CORS origins (prázdné = všem)

Admin Endpointy (bez Public API)

Admin a interní endpointy (bez _ prefixu) NEJSOU v whitelist a volají se přímý require z PHP:

// Admin - žádná ochrana (interní volání)
$output = Data\get('News/List');

// Frontend tagy - žádná ochrana (interní volání)
$output = Data\post('News/_latestThree', $data);

// CSRF a Rate Limit se NE aplikují - jsou to přímé PHP volání

Bezpečnostní Logování

Všechny pokusy o přístup jsou logovány:

Logger::setLog('security');
Logger::error('Unauthorized data endpoint access', [
    'ip' => $clientIp,
    'path' => $path,
    'user_agent' => $_SERVER['HTTP_USER_AGENT'],
]);

Logy jsou v var/log/security.log:

[2024-01-18 10:30:45] ERROR: Unauthorized data endpoint access - {"ip":"192.168.1.1","path":"/getData/News/Secret"}
[2024-01-18 10:31:10] ERROR: Rate limit exceeded - {"ip":"93.185.102.4","endpoint":"CookiesBar/updateLog","requests":25}
[2024-01-18 10:32:15] ERROR: Invalid CSRF token - {"ip":"10.0.0.5","endpoint":"CookiesBar/updateLog"}

Shrnutí

Typ Volání Middleware CSRF RateLimit Logging
Admin PHP Přímý require Ne Ne Ne Ne
Frontend tagy Přímý require Ne Ne Ne Ne
Public API (JS) HTTP fetch Ano (whitelist) Ano Ano (20/60) Ano