Route::SECURED a defaultFlags v HTTPS pod Nette 2.4
- David Grudl
- Nette Core | 8215
Přístup Nette k HTTPS si zasluhoval zrevidovat. Jednak se objevují issue, že by to chtělo nové flagy:
a také dochází k nedorozuměním, jaký smysl vlastně flag
IRouter::SECURED
má:
https://forum.nette.org/…je-https-100
Ve stručnosti: flag SECURED vznikl kdysi pradávno a proto, aby na HTTPS bylo možné Nette vůbec provozovat, tedy aby fungovala kanonizace. Což je unikátní vlastnost Nette, kdy se Presentery přesměrovávají na kanonickou URL, kterou vygeneruje router. A flag router instruuje k tomu, aby generoval odkazy s protokolem https. Nic víc, nic míň. Tedy aby nedocházelo k přesměrovávání z HTTPS na HTTP. Přičemž je mu jedno, ze kterého protokolu přicházíte, na to nehledí, ať už je flag aktivní nebo ne.
V žádném případě nefunguje jako zabezpečení proti vstupu přes HTTP. Na HTTPS se přesměrovává jen díky kanonizaci, což je věc spjatá se SEO, nikoliv bezpečností. Ke kanonizaci nemusí dojít, například při odeslání formuláře nebo ajaxovém požadavku. Přesměrování celého provozu by totiž měla zajistit konfigurace serveru, třeba v .htaccess.
Pokud celý web nebo subdoménu přesouvám na HTTPS, musím ve 2.3 všem
routám nastavit flag SECURED, což se dá zjednodušit tím, že nastavím
proměnnou Route::$defaultFlags
(statické proměnné nejsou
pěkné, je to jedna z posledních v Nette).
V nette 2.4 se routy chovají malinko jinak:
Při generování URL použijí stejný protokol, jaký aktuálně používáte
Pro weby, které běží kompletně na HTTPS, tak odpadá nutnost flag
uvádět a v důsledku toho mizí potřeba mít statickou proměnnou
$defaultFlags
.
Pro weby, které mají více subdomén a některé jsou na HTTPS a jiné
nikoliv (což není z bezpečnostního hlediska ideální), je stále
potřeba flag pro příslušné subdomény uvést (tj. u rout, jejichž maska
začíná na se místo flagu rovnou zapíše protokol
v masce.//
). V tomto případě ale také ztrácí smysl
$defaultFlags
.
U webů, které mají pod HTTPS jen určité stránky, tj. mají flag
SECURED uvedený u routy jejíž maska NEzačíná na //
, dojde
k vyhození noticky, že tento flag je deprecated. Toto upozornění má smysl,
protože flag SECURED skutečně nezajišťuje, že uživatel přišel na
stránku přes HTTPS, viz výše, a vlastně mohl vytvářet falešný pocit.
Uživatel musí přesměrování zajistit konfigurací serveru, třeba přes
.htaccess a flag může potom odstranit.
Proměnná $defaultFlags
je tedy deprecated a flag SECURED je
deprecated krom případu, že ho uvedete u routy s maskou začínající
na //
.
- greeny
- Člen | 405
Myiyk napsal(a):
Jak to bude fungovat v Nette 3 ?
Když to je teď deprecated, v Nette3 to nejspíš nebude. Přijde mi divné, aby potom šly dělat secured routy pouze na absolutní adresy.
Viz poznámka „pod čarou“ ->
V poslední verzi nette/application se routy chovají malinko jinak:
Při generování URL vedoucí na stejnou doménu a subdoménu, z jaké jste přišli, použijí stejný protokol.
Pro weby, které běží kompletně na HTTPS, tak odpadá nutnost flag uvádět a v důsledku toho mizí potřeba mít statickou proměnnou $defaultFlags.
- Myiyk
- Člen | 321
Ano, to je situace když vedou na stejnou doménu a subdoménu. Ale co
se stane, když ne? Bude odkaz https?
Už jsem to cca pochopil. Pokud routa bude relativní, použije se https podle
aktuální adresy. A když bude absolutní, půjde použít SECURED. + Bude asi
automaticky secured?
Editoval Myiyk (20. 5. 2016 21:00)
- Aurielle
- Člen | 1281
Vítám tuhle změnu, dost to zjednoduší nastavování rout na https-only webech. Díky!
Napadá mě jedna otázka: mám routy pro různé subdomény, všechny chci mít pod HTTPS. Musím uvádět nějaký flag nebo stačí konfigurací serveru zajistit, že budou přicházet pouze https požadavky a všechno bude fungovat správně?
- David Grudl
- Nette Core | 8215
Hmm, tohle jsem nedomyslel. Teď to funguje tak, že stejný protokol se používá při odkazu na stejnou doménu + subdoménu. Což znamená, že když mám vícesubdoménový web kompletně na HTTPS, musel bych u každé routy se subdoménou v masce (což jsou vlastně všechny) uvádět i flag SECURED…
Co s tím.
Protože web běžící komplet na HTTPS je ideální stav, mělo by tomu
být výchozí chování uzpůsobeno. Dalo by se to změnit tak, že se protokol
bude přenášet i při odkazech na jiné subdomény v rámci domény.
Rozlišit, co je doména a co subdomény je dost problém
(*.co.uk
), takže možná by bylo řešením to
nerozlišovat vůbec.
Co když některá subdoména na HTTPS není? Na to by se musel přidat nový
flag NONSECURED, ale říkám si, že srozumitelnější bude umožnit zápis
Route('http://domain.cz/<presenter>
)` a potažmo i
Route('https://domain.cz/<presenter>
), což by vlastně nahradilo flag SECURED. Zápis bez protokolu `Route('//domain.cz/<presenter>
)`
pak vlastně evokuje, že protokol bude přenášen, protože právě tak to
chodí i v prohlížečích.
- DavidKrmela
- Člen | 5
Pokud bude nové chování a způsob zápisu zachováno, bylo by možné
přidat krom placeholderů %basePath%
, %tld%
,
%domain%
a %sld%
také placeholder
%host%
? Aby šlo routy zapisovat stylem
Route('https://%host%/%basePath%/<presenter>')
, které šlo
dříve zapsat pomocí
Route('<presenter>', [], Route::SECURED)
.
- David Grudl
- Nette Core | 8215
Bude fajn, pokud něco vymyslíš a pošleš sem https://github.com/nette/docs
- Zuben45
- Člen | 268
David Grudl napsal(a):
Bude fajn, pokud něco vymyslíš a pošleš sem https://github.com/nette/docs
Dobrá tedy, nebyl jsem si jistý jestli by byl vůbec o to zájem :), zítra něco sepíši.
EDIT: @DavidGrudl PR – https://github.com/…ocs/pull/451
Editoval Zuben45 (7. 6. 2016 15:54)
- MKI-Miro
- Člen | 277
Ahojte
ako teda spravne nastavit https ?
momentalne to mam takto a chcel by som to prerobit na https
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ /www/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/www/
RewriteRule ^(.*)$ /www/$1
</IfModule>
dakujem
- David Matějka
- Moderator | 6445
@zerb kde mas hosting? neni ten apache za nejakou proxy, na kterou uz jde jen http(bez s) pozadavek?
- Jiří Nápravník
- Člen | 710
dneska jsem narazil na neco podobneho na onebitu: https://www.onehelp.cz/…oci-htaccess
- zerb
- Člen | 7
@DavidMatějka hosting mam na websupport.sk, doteraz som pouzival nette 2.3 a https routy som si vynutil cez secured flag v routerfactory, vsetko fungovalo. Po upgrade nette na 2.4 sa to rozsypalo, kedze flagy v routeri su deprecated. Sucasne s tym potrebujem requesty posielat do zlozky www. V .htaccess v korenovom adresari mam toto:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^$ /www/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_URI} !^/www/
RewriteRule ^(.*)$ /www/$1
</IfModule>
a tu potrebujem pridat este pravidlo aby requesty boli vzdy na https a sucasne ostalo posielanie requestov do zlozky www. Do apache konfiguracie sa nevyznam a neviem si s tym dat rady.
- alNath
- Člen | 17
Tiez som to tam riesil, zial nic neporiesil. Vid https://forum.nette.org/…tovani-https#…
- MKI-Miro
- Člen | 277
Ja som to vyriesil takto:
do websupportu som napisal aby mi zmenili root adresara do www adresara a v nom vyzera moje htaccess takto:
# Apache configuration file (see httpd.apache.org/docs/current/mod/quickreference.html)
# disable directory listing
<IfModule mod_autoindex.c>
Options -Indexes
</IfModule>
# enable cool URL
<IfModule mod_rewrite.c>
RewriteEngine On
#RewriteBase /
RewriteCond %{HTTP_HOST} !^www. [NC]
RewriteRule ^(.*)$ http://www.%{SERVER_NAME}%{REQUEST_URI} [L,R=301]
# use HTTPS
#RewriteCond %{HTTPS} !on
#RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R]
# prevents files starting with dot to be viewed by browser
RewriteRule /\.|^\.(?!well-known/) - [F]
# front controller
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule !\.(pdf|js|ico|gif|jpg|png|css|rar|zip|tar\.gz|map)$ index.php [L]
</IfModule>
# enable gzip compression
<IfModule mod_deflate.c>
<IfModule mod_filter.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript application/json application/xml image/svg+xml
</IfModule>
</IfModule>
- zerb
- Člen | 7
tak nakoniec sa mi to podarilo vyriesit, mozno niekomu pomoze tento kod. htaccess subor v zlozke www ostal nezmeneny a .htaccess v korenovom adresari som upravil takto:
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteCond %{HTTP:X-Forwarded-Proto} !=https
RewriteCond %{ENV:HTTPS} !^.*on
RewriteRule ^(.*)$ https://%{SERVER_NAME}/$1 [R,L]
RewriteRule ^$ /www/ [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ /www/$1
</IfModule>
- pavel_l
- Člen | 5
Zdravím.
Tato změna v Nette 2.4 mi přinesla problémy. Přesměrování na HTTPS potřebuji řešit v aplikaci, ne v .htaccess souboru. Jednak aplikace běží na větším množství domén a potom na serverech zákazníků. Také webový server do budoucna nemusí být jen Apache. Teď mám v aplikaci checkbox, kde si uživatel zvolí, jestli chce vynutit HTTPS nebo ne.
Nevidím ve 2.4 řešení, než dočasně potlačit E_USER_DEPRECATED. Myslel jsem, že bych vytvořil potomka třídy Route, ale to nejde protože proměnné objektu jsou private.
- David Grudl
- Nette Core | 8215
Přesměrování na https se musí řešit vždy na úrovni serveru, kvůli SEO apod. Jiné řešení Nette nepodporuje.