Formulář přes SSL
- DocX
- Člen | 154
Ahoj,
mohl by jste mě někdo nakopnout, jak nastavit formuláři, aby se odesílal přes HTTPS?
Celý web mám jinak bez SSL a jedná se o přihlašovací formulář, který je na každé stránce (vytvářený a zpracovávaný pomocí základního BasePresenteru)
Napadlo mě něco jako:
<?php
function createComponentLoginform()
{
$form = new AppForm($this, 'loginform');
...
$form->action = 'https' . substr($form->action, 4);
return $form;
}
?>
Ale přijde mi to jako prasárna :)
Díky :)
- Ondřej Mirtes
- Člen | 1536
Pro https se používá parametr Route::SECURED pro danou routu, takže bych dané stránce asi vytvořil speciální routu s tímto parametrem.
To, cos napsal, je fakt špatný :o))
- Panda
- Člen | 569
LastHunter napsal(a):
Pro https se používá parametr Route::SECURED pro danou routu, takže bych dané stránce asi vytvořil speciální routu s tímto parametrem.
To, cos napsal, je fakt špatný :o))
To nepůjde, protože by musel předělat celý web na https – formulář
má na každé stránce, je definovaný v BasePresenteru
. Taky jsem
chtěl napsat něco o IRouter::SECURED
, ale pak jsem si to
přečetl pořádně…
- DocX
- Člen | 154
On ten router bude dělat vlastně problém i tak, protože zabezpečený požadavek se bude snažit přesměrovat na nezabezpečený. Teda pokud bych nezměnil Router tak, aby mu bylo jedno přes jaký protokol byl obdržen request.
Nebo to možná vyřešit jinak, že by se formulář posílal do nějakého
konkrétního presenteru s backlinkem jako parametrem. Router na ten
zpracovávající presenter by se nastavil s Router::SECURED
,
takže by se měla action
na formuláři vytvořit sama
na https.
Jenže to taky nevím jak na to a tady z toho https://forum.nette.org/…jine-strance taky nejsem moc moudrý :(
- kravčo
- Člen | 721
Ja som vyššie spomínaný postup s dvoma routami použil úspešne (a
bezpečne). Dôležité je vedieť, že formulár sa musí zobraziť na
už zabezpečenej stránke – preto musí byť každá stránka, na
ktorej ho chceme zobrazovať, zabezpečená. U mňa má prihlasovací formulár na
starosti prezenter Security:Auth
, teda je to v poriadku.
$router[] = new SecureRouter(array(
'presenter' => 'Security:Auth',
'action' => 'default',
));
$router[] = new SimpleRouter(array(
'presenter' => 'Common:Home',
'action' => 'default',
));
class SecureRouter extends SimpleRouter
{
public function __construct($defaults = array(), $flags = 0)
{
parent::__construct($defaults, $flags | self::SECURED);
}
public function match(IHttpRequest $httpRequest)
{
// by default, SimpleRouter is greeeeedy...
if (!$httpRequest->isSecured()) {
return NULL;
}
return parent::match($httpRequest);
}
public function constructUrl(PresenterRequest $appRequest, IHttpRequest $httpRequest)
{
// by default, SimpleRouter is greeeeedy...
if ($appRequest->getPresenterName() !== $this->defaults[self::PRESENTER_KEY]) {
return NULL;
}
return parent::constructUrl($appRequest, $httpRequest);
}
}
Pripomienky a zdrby vítané :)
- DocX
- Člen | 154
Kravčo: To je celkem pěkné řešení, když máš přihlašovací formulář na jediné konkrétní stránce/presenteru.
Jenže já potřebuji mít formulář na všech stránkách, vytvářený v
BasePresenter
u a zobrazovaný v @layout.phtml
Nakonec jsem to vyřešil, ovšem znova až zásahem přímo do
Nette\Application\Presenter
(když to půjde takhle dál, budu mít
za chvíli vážně problém držet se aktuální verze Nette):
<?php
class Presenter
{
/** @var string */
- private $signalReceiver;
+ protected $signalReceiver;
/** @var string */
- private $signal;
+ protected $signal;
}
?>
<?php
class BasePresenter extends Presenter
{
function createComponentLoginform()
{
$form = new AppForm($this, 'loginform');
...
$form->action = $this->link('Login:dologin');
return $form;
}
}
?>
<?php
class LoginPresenter extends BasePresenter
{
function actionDologin()
{
$this->signal = 'submit';
$this->signalReceiver = 'loginform';
$this['loginform']->onSubmit[] = array($this, 'loginSubmitted');
$this['loginform']->signalReceived('submit');
$this->redirect('Homepage:');
}
function loginSubmitted(Form $form)
{
...
}
}
?>
a v routy mám takto:
<?php
//bootstrap.php
...
$router[] = new Nette\Application\Route('<lang>/login/dologin', array(
'lang' => null,
'presenter' => 'Login',
'action' => 'dologin',
), Nette\Application\Route::SECURED);
...
?>
Výsledek je, že formulář má
action="https://localhost/cs/login/dologin"
i na původně jen
http:// stránce. Po zpracování formuláře se přesměruje obět na ne-SSL
adresu.
Akorát to není asi úplně nejhezčí, ale opravdu mě nenapadá jak jinak na to :)
- DocX
- Člen | 154
oktam napsal(a):
Preco nie?
To by mě také zajímalo. Takto to má řešené například i centrum.cz, seznam.cz, apod.
Jinak bych musel mít https:// celý web, protože, jak jsem říkal, je to formulář na každé stránce (něco jako třeba na czc.cz)
Ale hlavně nevím, proč pro takto zdánlivě jednoduchou věc musím zasahovat do implementace Nette Presenteru. Buď za Boha nemůžu přijít jak na to Nette-way a nebo to skutečně Nette netankuje :)
Editoval DocX (24. 8. 2009 23:33)
- David Grudl
- Nette Core | 8227
kravčo napsal(a):
formulár sa musí zobraziť na už zabezpečenej stránke
Formulář se nemusí zobrazovat na https, stačí ho na https odesílat.
DocX napsal(a):
On ten router bude dělat vlastně problém i tak, protože zabezpečený požadavek se bude snažit přesměrovat na nezabezpečený.
Po odeslání formuláře Nette samo nikam nepřesměrováná.
Ale hlavně nevím, proč pro takto zdánlivě jednoduchou věc musím zasahovat do implementace Nette Presenteru. Buď za Boha nemůžu přijít jak na to Nette-way a nebo to skutečně Nette netankuje :)
Nette to netankuje. Budu tohle vlákno brát jako feature request.
- DocX
- Člen | 154
David Grudl napsal(a):
Formulář se nemusí zobrazovat na https, stačí ho na https odesílat.
Tak to je fajn :) Řešilo by to dost věcí. Vlastně by stačilo jenom nějak přesvědčit router, aby i když to nemá v definici routy vyrobil URL s https://.
Co jsem na to teď rychle koukal, tak by možná stačilo, aby se Router
řídil při rozhodování zda http:// nebo https:// i podle příznaků
nastavených v PresenterRequest
u. Pak už by stačilo jen přidat
nějaký parametr (flags nebo jen konkretně na SSL) metodám
Presenter::createRequest()
a
PresenterComponent::link()
(který by to předal createRequestu) a
ještě upravit třídu Link
, aby také uměla zacházet s těmito
příznaky.
Výsledek by mohl být ten, že kdykoliv by se tvořil link, mohlo by se
říci, že chci SSL (nebo naopak nechci), a on by se tak vytvořil. Ve
Form
u by to mohlo být nějak zapouzředné (třeba metodou
setSSL).
Akorát to tak trochu narušuje filozofii routů, že by pak aplikace věděla tak trochu o výsledné url.
Nette to netankuje. Budu tohle vlákno brát jako feature request.
Díky, jsem zvědav co nakonec vymyslíš :)
Editoval DocX (26. 8. 2009 13:01)
- kravčo
- Člen | 721
kravčo napsal(a):
Dôležité je vedieť, že formulár sa musí zobraziť na už zabezpečenej stránke – preto musí byť každá stránka, na ktorej ho chceme zobrazovať, zabezpečená.
Nepamätal som si, ako som svojho času tento názor prijal, teraz už viem.
Štandardná situácia je plain formulár a plain action. V tomto prípade môže útočník odpočúvajúci komunikáciu z POST požiadavky poľahky zistiť poslané údaje.
Pri plain formulári a zabezpečenej action prípadnú POST požiadavku čítať nemôže, to čo ale môže čítať (a aj podvrhovať) je stránka, na ktorej je formulár zobrazený. V princípe mu teda nič nebráni doručiť používateľovi stránku, ktorú chcel s len poupraveným action – napr. na svoj skriptík, ktorý zbiera heslá.
Pri zabezpečenej stránke s formulárom i akciou tento prístup nie je možný, keďže autenticita dát je overená. Samozrejme dá sa namietať, že podvrhnúť možno už odkaz na stránku s formulárom a áno, je to tak. Dôležitý rozdiel je v tom, že podvrhnutý odkaz na stránku s formulárom sa objaví v adresnom riadku a teda je možné naň prísť vcelku jednoducho. Na podvrhnutý action sa nedá prísť inak ako prezretím zdrojového kódu.
- DocX
- Člen | 154
kravčo napsal(a):
… Dôležitý rozdiel je v tom, že podvrhnutý odkaz na stránku s formulárom sa objaví v adresnom riadku a teda je možné naň prísť vcelku jednoducho. …
Kdyby už byl útočník uprostřed mojí komunikace, mohl by podvrhnout ten odkaz na stránku s formulářem tak, že by jen odstranil „s“ v https://.. Po té by podvrhl stránku s formulářem a dělo by se to, co jsi popsal. Uživatel by neměl šanci nic poznat.
Ale jinak jde o kokrétní situaci. Pokud půjde o e-banking tak budu mít celou aplikaci přes SSL. Pokud mi jde jen o relativně vyšší pocit bezpečí uživatelů, stačí mi zabezpečená akce.
Kdybych to vzal úplně do hloubky, tak mi ani celý web v HTTPS nemusí
zaručit bezpečí, protože když uživatel zadá
http://ebanking.cz
, může mi útočník nabídnout místo
přesměrování na https normálně stránku přímo na http. Může pak
fungovat jako nějaká proxy, kde z pohledu banky to jede normálně přes SSL,
mezi útočníkem a uživatelem to je nešifrovaný (proč řešit podvržený
certifikát ;) ). Samozřejmě jde o uživatele jestli si všimne toho, že mu
to neběží zabezpečeně.
Ale i kdyby si toho všiml, mohl mi můj dlohouletý „kamrád na drátě“ podvrhnout odkaz na stažení firefoxu a přibalit si do něj vlastní důvěryhodný certifikát. Případně, že mám ff z distribuce, mohl mi podvrhnout instalační CD distribuce. (Hm z toho mi vyplívá, že nejbezpečnější je asi koupenej Windows s IE)
Atd… ;)
Editoval DocX (26. 8. 2009 17:21)
- kravčo
- Člen | 721
DocX napsal(a):
kravčo napsal(a):
… Dôležitý rozdiel je v tom, že podvrhnutý odkaz na stránku s formulárom sa objaví v adresnom riadku a teda je možné naň prísť vcelku jednoducho. …
Kdyby už byl útočník uprostřed mojí komunikace, mohl by podvrhnout ten odkaz na stránku s formulářem tak, že by jen odstranil „s“ v https://.. Po té by podvrhl stránku s formulářem a dělo by se to, co jsi popsal. Uživatel by neměl šanci nic poznat.
Práve, že mal. V tvojom scenári nejde ani tak o text adresy ako o to, či je adresa šifrovaná alebo nie. To zväčša prehliadače dávajú výrazne najavo.
A ak používateľ bezpečnosť nijako nerieši, nepomôžeš mu…
- DocX
- Člen | 154
A ak používateľ bezpečnosť nijako nerieši, nepomôžeš mu…
S tím jsem ve svých úvahách počítal :) Navíc uživatel nemusí vědět že se měl ocitnout na HTTPS ;) Jinak s tebou samozřejmě souhlasím. Původně jsem myslel, že máš na mysli, že se změní na úplně jinou adresu :)
No ale ať uzavřem tento OT :) „Nejslabší článek je vždy uživatel…“
Editoval DocX (26. 8. 2009 18:51)
- David Grudl
- Nette Core | 8227
Tak fajn, ukončeme OT a zkusme navrhnout, jak by (globálně) měla podpora SSL v Nette fungovat.
- canonicalizace – otázkou je, jestli je fuk, jestli se na jednu stránku dívám přes https a nebo http; nejspíš ano, ale vidí to tak i Google? Chce to najít nějaké podklady.
- rozšíření Routeru, aby při generování přihlížel k flagu PresenterRequest::SECURED
- rozšíření Presenter::createRequest(), aby takový flag uměl nastavit
(tohle je dokonce napůl předpřipravené, odkaz lze psát jako
scheme://Presenter:action
, jen zatím se scheme ignoruje, bo není vymyšlená syntax. Použít https nebo ssl nebo secured?)
- Gringo
- Člen | 32
Já si zavedl do vlastní odvozeniny Route pole $secured
, které
určuje, co se má posílat přes SSL. V bootstrapu pak mám toto:
<?php
DbRoute::$secured = array(
'PlaceOrder', // cely presenter
'JobDirectory:postJob', // jenom action postJob
);
?>
Editoval Gringo (26. 8. 2009 23:39)
- DocX
- Člen | 154
David Grudl napsal(a):
- canonicalizace – otázkou je, jestli je fuk, jestli se na jednu stránku dívám přes https a nebo http; nejspíš ano, ale vidí to tak i Google? Chce to najít nějaké podklady.
Co jsem spěšně našel, tak to asi vidí skutečně jako duplicitu. Viz http://webtrh.cz/…ps-duplicita?…;
Tohle bych ale nechal jak je. Teď mě napadá, že by to možná chtělo vymezit jen na generování linků pro signály (jako je i form submit), co myslíš? Pokud se vlastně nejedná o signál, je to tedy klasická kombinace Presenter:action:params, tak se o adresu postará router (například tím způsobem, který napsal Gringo) a případně ji kanonizuje.
- rozšíření Routeru, aby při generování přihlížel k flagu PresenterRequest::SECURED
- rozšíření Presenter::createRequest(), aby takový flag uměl nastavit (tohle je dokonce napůl předpřipravené, odkaz lze psát jako
scheme://Presenter:action
, jen zatím se scheme ignoruje, bo není vymyšlená syntax. Použít https nebo ssl nebo secured?)
To s tím scheme://...
se mi docela líbí a přikláněl bych
se k syntaxy ‚secured‘ (presenter by měl být oddělen od toho, že HTTP
vůbec existuje).
Editoval DocX (27. 8. 2009 0:58)
- DocX
- Člen | 154
Gringo napsal(a):
<?php DbRoute::$secured = array( 'PlaceOrder', // cely presenter 'JobDirectory:postJob', // jenom action postJob ); ?>
Tyjo, tohle mi přijde vážně geniální :) Navíc by to mohlo řešit to, že si každý presenter může sám určit jestli chce být zabezpečený jednoduše přidáním se do routeru ve startupu :)
Takže co myslíte?
Měl by Presenter rozhodovat o tom zda a jaké akce budou zabezpečené (potom by na tu šel určitě udělat nějaký obecný mechanismus), tak, že by to oznámil routeru, který by poté případně požadavek kanonizoval
nebo
by mělo toto rozhodovací právo zůstat na Routeru a jeho nastavení v bootstrapu?
Editoval DocX (27. 8. 2009 0:21)
- David Grudl
- Nette Core | 8227
Podle Marka Prokopa je https vs. http také duplicitní obsah, nepřímo to zmiňuje i Petr Fidler. Viz také SEO konference.
- DocX
- Člen | 154
David Grudl napsal(a):
Podle Marka Prokopa je https vs. http také duplicitní obsah, nepřímo to zmiňuje i Petr Fidler. Viz také SEO konference.
Já jsem se v původním příspěvku překlepl (myslel jsem rozdílné stránky jakože to nevidí jako jednu a tutéž, ale jako 2 duplicitní).
Co to ale pro nás znamená? Myslím, že automatická kanonizace je jedna z klíčovích výhod Nette routeru. Na tom bych tedy nic neměnil. Měl jsem na mysli původně jen možnost SSL formuláře a ty vyhledávače neindexují.
Nebo jak jsi to myslel ty?
- Marek Malevič
- Člen | 2
Pekny den, chci se zeptat na stav teto problematiky. Prave resim stejny problem u jedne webove aplikace a tak me zajima, jestli nakonec (pripadne v jakem casovem horizontu) nejake reseni bude nebo mam radeji slevit ze svych predstav a prihlasovani resit na zvlastni strance.
Diky moc za odpoved.
- Honza Kuchař
- Člen | 1662
Taky si myslím, že by měla být stránka pouze zabezpečená nebo pouze nezabazpečená. Případně by byl redirect.
- Marek Malevič
- Člen | 2
Ja bych rad, aby mel guest neustale v me aplikaci moznost se prihlastit (formular bych chtel mit vzdy zobrazen) a chci, aby to odesilani jmena a hesla slo pres https. Zaroven mam ale vyrazne vykonnostni problemy pri pouzivani https (vzdycky se u DataGridu dlouho ceka z me neznameho duvodu) a to si u aplikace, kde se predpoklada aktivni prace uzivatele, nemuzu dovolit.
Protoze jedina informace, kterou chci sifrovat, je poslani hesla, pak bych opravdu uvital moznost odeslat heslo pres https, ale zbytek aplikace by dal pokracovala zase klasicky pres http.
Neni mi znam jediny duvod, proc by melo byt na zavadu takove reseni. V podstate neni zabezpecena nebo nezabezpecena stranka. Je pouze zabezpecena a nezabezpecena komunikace. A tu zabezpecenou vyzaduji pouze u hesla.
- DocX
- Člen | 154
Marek Malevič napsal(a):
Protoze jedina informace, kterou chci sifrovat, je poslani hesla, pak bych opravdu uvital moznost odeslat heslo pres https, ale zbytek aplikace by dal pokracovala zase klasicky pres http.
Jde to, já to vyřešil následovně:
<?php
// BasePresenter:
function createComponentLoginForm()
{
$form = new AppForm();
...
// odkaz na action "dologin" v "LoginPresenter"
$form->action = $presenter->link('Login:dologin');
}
// v bootstrapu pridat zabezpecenou routu, aby se link vyse vytovril s https://
$router[] = new Nette\Application\Route('login/dologin', array(
'presenter' => 'Login',
'action' => 'dologin',
), Nette\Application\Route::SECURED);
?>
Neni mi znam jediny duvod, proc by melo byt na zavadu takove reseni. V podstate neni zabezpecena nebo nezabezpecena stranka. Je pouze zabezpecena a nezabezpecena komunikace. A tu zabezpecenou vyzaduji pouze u hesla.
Duvod tam je.
Pokud by se nekdo dostal k moznosti jen slyset komunikaci (napr. bydli v baraku na jehoz srese je AP s nesifrovanym „signalem“ na nejz se pripojuje okolnich 10 baraku), tak to staci.
Predstav si ale ze se dostane nejakym zpusobem mezi (man in the middle), tzn ze komunikaci nejen ze slysi, ale muze ji i menit. Pak to nestaci, protoze v okamziku, kdy tvuj server posila nesifrovanou (a nepodepsanou) stranku s formularem, on v ni zmeni prislusnou hodnotu v action na http:// (bez „s“), klidne i stejne adresy. Jakmile pak uzivatel formular odesle (pres ne-ssl), data pujdou znovu skrz nej. K tvemu serveru se prihlasi jakoby on pres SSL a odezvu prelozi zpet uzivateli, aby nic nepoznal. Kdyby jsi ale mel cely web zabezpeceny s certifikatem podepsanym znamou autiritou, tohle by neslo. Teda slo, kdyby utocnik zamezil pristupu uzivatele na SSL, treba by zmenil odkaz ve vysledku google. Je ale fakt, ze dostat se nekomu doprostred komunikace je celkem obtizne.
Doufam ze u nas jeste neni trestne zverejnovani takovychto informaci :o))