vojta 4520137240 Nepoužívat mb_strlen() pro validaci uživatelského jména
Jméno je hned za tím validované regexem jen na ASCII znaky, takže
mb_strlen() byl zbytečný a navíc vyžadoval rozšíření mbstring, které
na produkčním serveru chybělo a shazovalo registraci s 500.
2026-08-05 12:41:33 +02:00

Registrace účtů — AzerothCore

Jednoduchá PHP registrační stránka pro AzerothCore server. Vytváří účet přímo v acore_auth.account tabulce se správně spočítaným SRP6 salt/verifierem, takže se hráč může rovnou přihlásit ve hře.

Ochrana proti spamu/botům

  • Cloudflare Turnstile — captcha ověřená server-side (volitelná: pokud necháš TURNSTILE_SITE_KEY/TURNSTILE_SECRET_KEY prázdné, widget se nezobrazí a ověření se přeskočí — pro produkci ale doporučuji vyplnit).
  • Honeypot pole — skryté pole website, které boti často vyplní; formulář pak předstírá úspěch, ale nic se nezapíše.
  • Rate limiting — max. N registračních pokusů z jedné IP za časové okno (výchozí 5 / hodinu), ukládá se do lokální SQLite (data/ratelimit.sqlite), nezasahuje do AzerothCore databáze.
  • CSRF token na formuláři.

Požadavky na serveru

  • PHP 8.1+
  • PHP rozšíření: pdo_mysql, pdo_sqlite, gmp, session, openssl
  • Webserver (Apache s mod_php/PHP-FPM, nebo nginx + PHP-FPM)
  • Síťový/lokální přístup k MySQL, kde běží acore_auth

Instalace

  1. Naklonuj repozitář na server, mimo webroot ostatních webů (např. vedle PlayerMap):

    git clone https://gitea.minkey.cz/vojta/wow-registrace.git
    cd wow-registrace
    
  2. Zkopíruj .env.example do .env a vyplň:

    • SITE_NAME, REALMLIST_ADDRESS (wow.minkey.cz), CLIENT_VERSION, případně CLIENT_DOWNLOAD_URL — zobrazují se na úvodní stránce
    • DB_HOST, DB_PORT, DB_DATABASE (typicky acore_auth), DB_USERNAME, DB_PASSWORD
    • TURNSTILE_SITE_KEY / TURNSTILE_SECRET_KEY z Cloudflare dashboardu

    .env se negituje (je v .gitignore) — na serveru ho vytváříš ručně, nikdy ho nepushuj do repozitáře.

  3. Vytvoř v MySQL dedikovaného uživatele jen s právy na tabulku account (neházej tam root přístup):

    CREATE USER 'acore_reg'@'localhost' IDENTIFIED BY 'silne-nahodne-heslo';
    GRANT SELECT, INSERT ON acore_auth.account TO 'acore_reg'@'localhost';
    FLUSH PRIVILEGES;
    
  4. Nastav webserver tak, aby DocumentRoot mířil na public/, ne na kořen projektu — includes/, data/ a .env tak nebudou z webu dostupné vůbec.

    Příklad Apache vhost (port 80 — HTTPS řeší reverzní proxy před tímhle serverem, viz sekce níže; pokud Apache vystavuješ na internet přímo bez proxy, dej sem *:443 a přidej SSL certifikát):

    <VirtualHost *:80>
        ServerName wow.minkey.cz
        DocumentRoot /var/www/wow-registrace/public
    
        <Directory /var/www/wow-registrace/public>
            AllowOverride All
            Require all granted
        </Directory>
    </VirtualHost>
    

    Příklad Nginx + PHP-FPM (uprav fastcgi_pass podle svého PHP-FPM socketu, stejně jako to máš u PlayerMap):

    server {
        listen 80;
        server_name wow.minkey.cz;
        root /var/www/wow-registrace/public;
        index index.php;
    
        location / {
            try_files $uri $uri/ =404;
        }
    
        location ~ \.php$ {
            include fastcgi_params;
            fastcgi_pass unix:/run/php-fpm/php-fpm.sock;
            fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        }
    
        # includes/, data/ a .env jsou mimo document root, takže už jsou
        # skryté; tenhle blok je jen pojistka, kdyby se root někdy spletl
        location ~ /\.(env|git) {
            deny all;
        }
    }
    
  5. Uprav práva zápisu na data/ (potřebuje tam vzniknout ratelimit.sqlite) — uprav uživatele podle toho, pod kterým webserver skutečně běží (www-data na Debianu/Ubuntu, http na Arch, nginx apod.):

    chown -R www-data:www-data data
    chmod 750 data
    
  6. Ověř, že GMP na serveru počítá SRP6 verifier správně (porovná se s nezávisle spočítanou referenční hodnotou):

    php includes/srp6_selftest.php
    

    Očekávaný výstup je OK - shoduje se s referenční implementací. Pokud vypíše chybu, něco je špatně s PHP/GMP na serveru a registrace by vytvářela účty, se kterými se nepůjde přihlásit — než to nespadne, dál nepokračuj.

  7. Otevři stránku v prohlížeči, vyzkoušej registraci, ověř že se v account tabulce objevil nový řádek a že se přihlásíš herním klientem.

Nasazení za reverzní proxy (Nginx Proxy Manager, Cloudflare, ...)

Pokud HTTPS řeší proxy před tímto serverem (např. Nginx Proxy Manager), Apache/Nginx tady běží jen na HTTP (viz vhosty výše) a proxy dotazy předává dál. Je potřeba:

  1. V Nginx Proxy Manageru přidat nový Proxy Host:

    • Domain Names: wow.minkey.cz
    • Forward Hostname/IP + Port: adresa a port 80, na kterém poslouchá Apache/Nginx s tímhle vhostem (stejně, jak už máš nastavené pro PlayerMap, jen jiná doména)
    • Na záložce SSL: Request a new SSL Certificate (Let's Encrypt) + zapnout Force SSL
  2. V .env nastavit:

    TRUST_PROXY_HEADERS=true
    

    Bez tohohle by aplikace u každého požadavku viděla jako "IP klienta" IP samotné proxy, a rate limiting proti spamu by tak omylem počítal všechny návštěvníky jako jednoho. Zapínej to jen tehdy, když Apache port 80 na tomhle serveru není z internetu dostupný přímo (jen skrz tu proxy) — jinak si útočník IP adresu v hlavičce jednoduše vymyslí a rate limiting/logy přestanou dávat smysl.

Aktualizace

cd /cesta/k/wow-registrace
git pull

.env a data/ratelimit.sqlite nejsou v repozitáři, takže git pull je nepřepíše.

Poznámky k herním pravidlům

  • Uživatelské jméno i heslo se před výpočtem SRP6 verifieru převádí na velká písmena (strtoupper) a jméno se tak i ukládá — přesně jak to dělá samotný AzerothCore/klient, aby přihlášení fungovalo case-insensitive.
  • Heslo je omezené na tisknutelná ASCII znaky (REG_PASSWORD_MIN/MAX v .env, výchozí 816 znaků) — WoW klient jiné znaky v hesle nepodporuje.
  • expansion, locale a další sloupce tabulky account se nechávají na výchozích hodnotách definovaných v DB schématu AzerothCore — uprav public/register.php, pokud chceš nový účet zařadit jinak (např. jiný expansion level).
  • Pokud web neběží přímo na stejném stroji jako MySQL, zvaž TLS pro DB spojení nebo tunelování (SSH tunel / VPN), ať heslo/verifier neputuje po síti čistě.

Struktura projektu

includes/        # PHP logika mimo webroot (DB, SRP6, Turnstile, rate limiter)
public/          # webroot — index.php (formulář), register.php (zpracování)
data/            # SQLite pro rate limiting (zapisovatelné webserverem)
.env             # tajné údaje, needituj do gitu
S
Description
No description provided
Readme 1 MiB
Languages
PHP 70.1%
CSS 29.9%