Abych si přiblížil vývoj na lokálním počítači tomu
ostrému, zprovoznil jsem si lokální https. Jak na to?
Nejsnazší cesta
V komentářích padla zmínka o aplikaci mkcert, která následující
postup udělá za vás. Ale pokud máte rádi ruční práci, čtěte
dál :)
Vygenerujeme SSL certifikát
K tomu použijeme program openssl
, který určitě na
počítači najdete, třeba jako součást Gitu na
C:\Program Files\Git\usr\bin\openssl.exe
nebo jinde. Následující
příkaz vygeneruje klíč do souboru rootCA.key
. Bude to po vás
chtít vymyslet nějaké heslo, které si uložte.
openssl genrsa -des3 -out rootCA.key 2048
Další příkaz z klíče vygeneruje kořenový SSL certifikát a uloží
ho do souboru rootCA.pem
. Jeho platnost bude 2000 dní (tedy pět
let), ale číslo klidně změňte:
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 2000 -out rootCA.pem
Uvěříme certifikátu
Teď oznámíme operačnímu systému, aby certifikát považoval za
důvěryhodný. Postup pro Mac jsem našel třeba
tady, pro Windows je pěkně obrázek za obrázkem sepsaný
zde a pro české Windows jsem vám jej přeložil:
- spustit mmc
- v menu Soubor > Přidat nebo odebrat moduly snap-in
- doubleclick na Certifikáty v levém okně
- zvolte Účet počítače a Další
- ponechte Místní počítač a Dokončit
- zavřete okno tlačítkem OK
- v levém okně zvolte Certifikáty, v pravém Důvěryhodné kořenové
certifikační autority
- pravé tlačítko a v kontextovém menu Všechny úkoly >
Importovat
- objeví se Průvodce importem certifikátu, dejte Další
- vyberte soubor
rootCA.pem
a odklikejte průvodce na konec
Ufff, jsme v půlce. Pokračujeme v Konzoli:
- opět v menu Soubor > Přidat nebo odebrat moduly snap-in
- doubleclick na Editor objektů zásad skupiny
- stiskněte Dokončit a zavřete okno tlačítkem OK
- v levém okně otevřete Místní počítač – zásady > Konfigurace
počítače > Nastavení systému Windows > Nastavení zabezpečení >
Zásady veřejných klíčů
- doubleclick na Nastavení ověření cesty certifikátů
- zatrhněte Definovat tato nastavení, Povolit ověřování certifikátů
… a Povolit uživatelům důvěřovat certifikátum …
- potvrďte tlačítkem OK
Hotovo, zavřete Konzoli.
Všichni už certifikátu věří, akorát Firefox chce ještě
popostrčit:
- ve Firefoxu otevřete stránku
about:config
- odklikejte všechna varování
- vyhledejte položku
security.enterprise_roots.enabled
- doubleklikem změňte hodnotu na true
- zavřete stránku
Vyrobíme certifikát pro
webový server
Klikačku máme za sebou, teď vyrobíme certifikáty pro server. Vytvoříme
soubor server.csr.cnf
s tímto obsahem:
[req]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
[dn]
C = CZ
ST = Random
L = Random
O = Random
OU = Random
emailAddress = example@example.com
CN = localhost
A dále soubor v3.ext
, kde bude uveden seznam všech domén,
které na localhostu provozujete:
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = localhost
DNS.2 = texy.l
DNS.3 = *.texy.l
DNS.4 = nette.l
DNS.5 = *.nette.l
DNS.6 = navlnachekg.l
Jak vidíte, lokální verze webů provozuji na doménách, které končí na
.l
, u vás to třeba bude jinak. Ty jednotlivé klíče
DNS.1
apod. je potřeba fakt jako idiot postupně očíslovat.
Následujícím krokem vygenerujeme soubory server.key
aserver.csr
:
openssl req -new -sha256 -nodes -out server.csr -newkey rsa:2048 -keyout server.key -config server.csr.cnf
A konečně vygenerujeme SSL certifikát pro server do
server.crt
(teď to bude po vás chtít zadat heslo, které jste si
vymysleli na začátku):
openssl x509 -req -in server.csr -CA rootCA.pem -CAkey rootCA.key -CAcreateserial -out server.crt -days 500 -sha256 -extfile v3.ext
Všechny dosud vytvořené soubory včetně hesla si někam uložte. Ať se
totiž změní domény, které provozujete lokálně, jen upravíte
v3.ext
a posledním příkazem znovu vygenerujete certifikát pro
server.
Konfigurace webového serveru
Zbývá povolit https na serveru. Tj. nakonfigurovat server tak, aby
naslouchal na portu 443, na kterém běží https, a používal vygenerovaný
certifikát.
Používám Apache, do jehož konfiguračního soubor httpd.conf
jsem přidal následující řádky s cestou k souborům
server.key
aserver.crt
:
Listen 443
SSLCertificateFile "C:\Apache24\ssl\server.crt"
SSLCertificateKeyFile "C:\Apache24\ssl\server.key"
Konfiguraci virtuál hostů možná řešíte úplně jinak než já, těžko
říct, ale v mém případě zprovoznění obnášelo ke každému virtuálu
jako je
<VirtualHost *>
ServerName localhost
DocumentRoot "W:/"
</VirtualHost>
doplnit ještě druhý:
<VirtualHost *:443>
ServerName localhost
DocumentRoot "W:/"
SSLEngine on
</VirtualHost>
V nginx by mělo stačit do konfiguračního souboru nginx.conf
doplnit pro každý server něco takového:
server {
listen 443 ssl;
ssl_certificate path/to/server.crt;
ssl_certificate_key path/to/server.key;
}
A to je vše. Docela mazec, co? Otevřete v prohlížeči
https://localhost
a jestli se stránka zobrazí, je to důvod
k oslavě.
Stránky Nette existují ve dvou jazykových verzích: české
a anglické. Udržovat tak obsáhlý projekt ve dvou mutacích vyžaduje dost
práce, ale vidím v tom smysl.
Plnohodnotná česká dokumentace a fórum je totiž výhodou pro zdejší
začínající programátory, protože žádný jiný framework ničím takovým
nedisponuje. Samozřejmě ideální by bylo, kdyby každý Čech už od
základní školy uměl plynně anglicky, ušetřilo by to hodně práce, ale
není úkolem frameworku tohle suplovat. Nicméně angličtina není
v žádném případě druhotným jazykem. Naopak. Posuďte sami:
Dokumentace. Její současná velikost
čítá 3 MB textů (pro srovnání celé
dílo Shakespeare má 5 MB). Anglická a česká jsou přitom zcela identické.
Nejsem si vědom, že by jeden jediný odstavec existoval třeba v české
verzi a anglické chyběl. Případně by se v jedné verzi objevil mnohem
dříve než v druhé. Obě verze jsou neustále synchronizované. Pokud byste
na nesoulad narazili, vytvořte prosím issue na GitHubu.
Anglické forum bylo spuštěno v roce
2008. Na českém až do minulého týdne svítila zpráva: „Chcete se
zdokonalovat v angličtině? Zkuste psát do anglického fóra. I když by to
bylo s chybami – těmi se člověk učí.“, takže i mnoho Čechů
používá anglické fórum.
Nette Blog v tuto chvíli čítá
34 článků v angličtině a 19 v češtině. Rozhodně doporučuji blog
sledovat, třeba přes RSS,
stává se z něj hlavní zdroj informací o novinkách.
Diskuse na GitHubu jsou výhradně v angličtině. Tuším od roku 2012 je
to oficiální podmínka. Jedinou výjimkou jsou diskuse o české dokumentaci,
což je snad pochopitelné.
V celém kódu se nikdy neobjevilo jediné české slovo. Kód je od
prapočátků pouze v angličtině, včetně všech chybových hlášek,
komentářů atd. Tuším jen jednou se v něm vyskytlo slovo fuck 🙂
Dále je tu oficiální Twitter
kanál, který je od počátku kompletně anglicky.
Co naopak anglicky není? Tak především jsou to videa z Posobot a
facebooková stránka Nette Framework
CZ/SK, která slouží zejména k informování o lokálních akcích,
jako je právě Posobota nebo NettePivo. A taky kanál na Slacku
Péhápkaři, což tedy není oficiální součást Nette.
Ještě pár technických záležitostí: pokud přijdete na úvodní
stránku webu, fóra či blogu, nejspíš vás to přesměruje na českou verzi.
Je to pouze proto, že máte v prohlížeči nastavený jako preferovaný jazyk
češtinu nebo jste se už někdy v minulosti do české mutace přepnuli.
Jinak samozřejmě přesměrovává na anglickou verzi.
Taktéž je určitý rozdíl mezi výpisem článků či příspěvků na
českém a anglickém fóru. Web zkrátka předpokládá, že český uživatel
anglicky číst umí, takže českým uživatelům se například u nejnovějších příspěvků
vypisují i ty anglické nebo na českém blogu i anglické články,
u který neexistuje českých překlad. Zahraniční uživatel tento mix
nevidí.
Česká verze je zkrátka přidaným komfortem. Ale rozhodně preferujeme
tvořit obsah v angličtině.
Článek vyšel na blogu
Nette.
Článek vyšel na blogu
Nette.
Článek vyšel na blogu
Nette.
Content Security Policy (CSP) je dodatečný bezpečnostní prvek, který
prohlížeči říká, jaké další zdroje může stránka načítat a jak
může být zobrazena. Chrání tak před vkládáním škodlivého kódu a
útokům jako je XSS. Odesílá se v podobě hlavičky sestavené z řady direktiv.
Jeho nasazení ale není vůbec triviální.
Obvykle chceme používat JavaScriptové knihovny umístěné na různých
místech mimo náš server, například měřící kód Google Analytics,
reklamní systémy, captchy atd. A tady bohužel první verze CSP selhává.
Vyžaduje přesnou analýzu načítaného obsahu a nastavení správných
pravidel. Tedy vytvořit whitelist, výčet všech domén, což není snadné,
jelikož některé skripty dynamicky dotahují další skripty z jiných
domén, nebo jsou na jiné domény přesměrované atd. A i když si dáte
práci a seznam vytvoříte ručně, nikdy nevíte, co se může v budoucnu
změnit, takže musíte neustále sledovat, jestli je seznam stále aktuální a
opravovat ho. Analýza Google ukázala, že i to pečlivé ladění ve finále
vede k tomu, že povolíte tak široký přístup, že celý smysl CSP padá,
jen posíláte s každým požadavek mnohem větší hlavičky.
CSP level 2 už k problému přistupuje jinak, pomocí nonce, nicméně
teprve třetí verze řešení dotáhla do konce. Bohužel zatím (rok 2019)
nemá dostatečnou podporu u prohlížečů.
O tom, jak sestavit direktivy script-src
a
style-src
, aby správně fungovaly i ve starších
prohlížečích a přitom s tím bylo co nejméně práce, jsem sepsal podrobný
článek v partnerské sekci Nette. V zásadě výsledná podoba může
vypadat nějak takto:
script-src 'nonce-XXXXX' 'strict-dynamic' * 'unsafe-inline'
style-src 'nonce-XXXXX' * 'unsafe-inline'
Příklad použití v PHP
Vygenerujeme nonce a odešleme hlavičku:
$nonce = base64_encode(random_bytes(16));
header("Content-Security-Policy: script-src 'nonce-$nonce' 'strict-dynamic' * 'unsafe-inline'");
A vložíme nonce do HTML kódu:
<script nonce="<?=$nonce?>" src="..."></script>
Příklad použití v Nette
Protože Nette má vestavěnou podporu pro CSP a nonce od verze 2.4, stačí
v konfiguračním
souboru uvést:
http:
csp:
script-src: [nonce, strict-dynamic, *, unsafe-inline]
style-src: [nonce, *, unsafe-inline]
A v šablonách pak používat:
<script n:nonce src="..."></script>
<style n:nonce>...</style>
Monitoring
Než nastavíte nová pravidla pro CSP, vyzkoušejte si je nejprve nanečisto
pomocí hlavičky Content-Security-Policy-Report-Only
. Ta funguje
ve všech prohlížečích podporujících CSP. Při porušení pravidel
prohlížeč nezablokuje skript, ale jen pošle notifikaci na URL uvedené
v direktivě report-uri
. K příjmu notifikací a jejich analýze
můžete použít třeba službu Report
URI.
http:
cspReportOnly:
script-src: [nonce, strict-dynamic, *, unsafe-inline]
report-uri: https://xxx.report-uri.com/r/d/csp/reportOnly
Můžete zároveň používat obě hlavičky a v
Content-Security-Policy
mít ověřené a aktivní pravidla a
zároveň v Content-Security-Policy-Report-Only
si testovat jejich
úpravu. Samozřejmě i selhání ostrých pravidlech si můžete nechat
monitorovat.
Po dvou verzích PHP, které nepřinesly nic moc zajímavého, se blíží
verze, pro kterou bude mít opět smysl aktualizovat knihovny. Jde o PHP 7.4 a
hlavním tahákem jsou typed properties, které
uzavírají mnohaletý posun ke striktně typovanému jazyku, což PHP
zvýhodňuje oproti jiným webovým jazykům.
Ve zkratce, tahle novinka vám umožní deklarovat typy přímo
u proměnných třídy:
class Config
{
public string $dsn;
public ?string $user;
public ?string $password;
public bool $debugger = true;
}
Příklad použití najdete i v dokumentaci
Nette Schema, které je na ně už dnes připravené.
Je potřeba říct, že pokud jste si navykli používat privátní
proměnné a přistupovat k nim přes typehintované metody (což je
správně), tak vlastně o žádnou killer feature nejde. Druhotná kontrola
typů je zbytečná a vlastně jen zpomaluje kód. Diametrálně jiná situace
se týká public/protected proměnných, kde dosud neexistoval žádný způsob,
jak mít jejich hodnotu (a dokonce existenci) pod kontrolou. Až dosud.
Což nevyhnutelně povede k otázce:
Je nutné dál psát settery a
gettery?
Sice veškerý boilerplate kód nám dnes na kliknutí generují editory, ale
určitě vypadá hezky, když tohle:
class Circle
{
private $radius;
function setRadius(float $val)
{
$this->radius = $val;
}
function getRadius(): float
{
return $this->radius;
}
}
nahradíte za:
class Circle
{
public float $radius;
}
Nehledě na to, že i užití objektu je stručnější
$circle->radius = $x
vs
$circle->setRadius($x)
.
Problém ale je, že velkou spoustu setterů a getterů nelze jednoduše
nahradit. Třeba zrovna v uvedeném příkladu by se hodilo ještě ověřit,
že poloměr není záporné číslo:
function setRadius(float $val)
{
if ($val < 0) {
throw new InvalidArgumentException;
}
$this->radius = $val;
}
A v ten moment už nelze kód zredukovat do veřejné proměnné.
Jindy zase chceme, aby jednou nastavená hodnota byla neměnná, což nelze
u public proměnné zajistit.
Nebo vůbec nechceme dávat k dispozici getter, protože nepatří do
veřejného API třídy.
Anebo chceme mít setter či getter součástí rozhraní.
Atd, atd.
Zkrátka někdy bude možné použít typované veřejné proměnné místo
metod, jindy ne, rozdíl bude dost často otázkou vnitřní implementace
třídy a pro uživatele neprůhledný. Což je cesta v nekonzistentnímu API,
kdy jednou se používá proměnná, jindy metoda a uživatel v tom nevidí
logiku. (Podobně jako třeba metoda PDOStatement::errorInfo()
vs.
proměnná PDOException::$errorInfo
).
Prohlubování nekonzistence ale nechceš. Raději konzistentní setrvání
u metod, privátních proměnných a všeho toho boilerplate kódu. A pro
privátní proměnné, jak jsem zmiňoval v úvodu, je přínos typehintů
sporný. Nebo ne?
V čem je tedy výhoda?
Vlastně je výhod dost, i když v jiných oblastech. Typované proměnné
budou užitečné pro kompilátor kvůli optimalizacím, pro práci s reflexí
nebo nástroje analyzující kód. Důležité budou v šedé zóně protected
proměnných. Umožňují zapsat prostředky jazyka to, co se dosud obcházelo
komentářem. A navíc přinášejí do jazyka nový příznak neinicializovaného
stavu, jakousi obdobu undefined
z JavaScriptu.
Něco jako když zahlédnete plakát ke koncertu kapely, kterou
si vybavujete z mládí. Oni stále hrají? Nebo se dali dohromady po letech,
protože potřebují peníze? Něco vyždímat na strunách nostalgie?
Texy je můj první open source projekt. Začal jsem ho psát před patnácti lety.
Texy přežilo několik verzovacích systémů. Několik webových služeb
hostujících repositáře. Několik kódování řetězců. Několik
značkovacích jazyků pro tvorbu webových stránek. Několik mých životních
vztahů. Několik měst, ve kterých jsem bydlel.
Texy je tady stále, protože neexistuje nic
lepšího.
Takže jej patnáct let udržuji up-to-date. Začínali jsme v PHP 4, což
byl ten nejhorší programovací jazyk na světě a tedy výzva, pak s úlevou
přešli na PHP 5, o pár let později se ukryli do jmenného prostoru
(Texy::Parser
místo TexyParser
, wow), sledovali, jak
PHP přestávalo být nejhorším jazykem na světě, což otrávilo spoustu
programátorů, kteří si našli náhradu v JavaScriptu, poté bůh stvořil
PHP 7 a s ním typehinty (Texy::process(string $text): string
megawow) a do módy přišla striktnost declare(strict_types=1)
a
tu my ctíme.
A proto je tu Texy 3.0.. Jde
o úplně totéž, jako předchozí verze, ale má všechny vychytávky PHP
7.1. Je to úplně totéž proto, že do dokonalých věcí se nezasahuje.
Texy tu bylo, když jste se narodili. Programátorsky. Texy jednou bude
formátovat váš epitaf. A mezi v
a pokoji
vloží
nedělitelnou mezeru.
V tu-dů listu mi
už druhý týden visí: „Sepsat článek, proč podporovat Nette.“
A zatímco jsem to odkládal, tak kluci z Freelo mě předběhli a napsali to
tak moc dobře, že už nemá smysl se o něco pokoušet 🙂
Díky moc! A tady je 14 důvodů, proč
podpořit Nette.
Co přinesou příští verze Nette Frameworku a jaký je plán
pro další vývoj?
Nette je tvořeno řadou knihoven, z nichž některé patří mezi světovou
špičku: Latte je nejbezpečnější
šablonovací systém, Tracy je mnohými
považován za nejpřívětivější debugovací nástroj, Dependency Injection
Container patří mezi ty nejpohodlněji použitelné. Spousta konceptů vznikla
šťastnou rukou a fungují v prakticky nezměněné podobě už 10 let,
například formuláře nebo komponentový systém presenterů.
Nicméně ve všech oblastech je hodně příležitostí co vylepšovat a
inovovat. A nápadů je spousta.
…pokračování