Používání ACL a zabezpečení formuláře, metody isAllowed
- joe
- Člen | 313
Ahoj,
už nějakou dobu Nette používám a zatím jsem si vždycky vystačil
s jednoduchou autorizací pomocí metod isLoggedIn
a
isInRole
. O možnosti vlastní autorizace vím, jen jsem zatím
neměl potřebu ji nikde použít.
Přichází na řadu nějaké ACL, díky dobrému článku na statický ACL
Hned mě napadají tyto dotazy:
- Je to sice pěkné a funkční, ale po dokončení aplikace ji musím celou projít, nastavit zdroje (tzn. všechny presentery) a privilegia (akce presenterů). Pokud něco někde změním nebo doplním, musím na to myslet a poté ACL upravit. Jednodušeji to asi nejde? :)
- Bezpečnost a nastavení práv k odeslání formuláře. Co když budu mít v jednom presenteru více akcí a k některým budou mít přístup jen nějaké role. Pokud by v jedné z nich byl formulář, jak kontrolovat zda daná role má právo formulář odeslat? Pokud se nepletu, formulář bych mohl odeslat (tj. obejít zabezpečení) přes nějakou akci, ke které mám přístup. To bych měl vyřešit jak?
- Metodu/y isAllowed psát taky do modelů? Někde jsem četl, že by měly být až tam a ne řešit to na úrovni presenteru.
Díky za odpovědi od zkušenějších ;-)
- Matúš Matula
- Člen | 257
- robim to tak isto, ak to ide jednoduchsie, budem len rad :)
- kontroluj prava v
onSuccess[]
(onSubmit[]
) metode, ne vactionXYZ
, resp. vid bod 3 - kontrolujem na urovni modelov a vyhadzujem vynimky, kt. odchytavam v presenteroch..Mas to v jednom mieste a viaze sa to priamo na akciu, na ktoru sa to viazat ma :)
- joe
- Člen | 313
Matúš Matula:
díky
1 – Proto jsem to radši dělal bez ACL, protože to je jednak rychejší (edituju jen jeden soubor), nemusím myslet na změnu při připsání nové akce a navíc po kouknutí do kódu ihned vidím, jak se bude pro danou roli chovat (pokud je nějak omezena).
2 – jasné, musím kontrolovat po odeslání (tedy onSuccess) a to pro každý takový formulář pak vymyslíš jméno jako název privilegia?
3 – zdá se mi to taky dobré kontrolovat to až v modelech (a při renderování v šabloně pro zobrazení/skrytí)
- newPOPE
- Člen | 648
Pokial pouzivas formulare ako samostatne triedy tak nic vymyslat nemusis. Do daneho formulara este mozes injektnut usera a kontrolovat priamo v nom. resp sa buildne inak tomu a inak tomu…
tot moje riesenie (nikdy nepouzite, ale domnievam sa, ze ta prva vec by sla automatizovat)
- newPOPE
- Člen | 648
joe tiez som v minulosti vyrabal priamo v presenteroch, teraz uz to nerobim. Pozeram na to skor opacne. Scroll alebo Klik na iny subor ;-) (NBeans ma skratky, cize je to jedno), co je jednoduchsie? To ale problem nie je. Skor je problem (a to dost velky) ked ten projekt uvidis po čase a kym sa z toho vysomaris tak mozes (nemusis) stratit hodnú chvilu.
Dalsi dovod preco pouzivam formulare ako samostatne triedy
- mozem ich pouzit cross APP
- su v podstate komponenta, ktora robi nieco sama, mozem si ju nastavit
- skus to a uvidis ci je to lepsie alebo nie
- nanuqcz
- Člen | 822
Pokial pouzivas formulare ako samostatne triedy tak nic vymyslat nemusis.
Můžu se zeptat proč? Nějak mi nedochází, v čem je přístup formulářů jako samostatné třídy ve výsledku jiný…
EDIT: Chápu to dobře, že to byla odpověď na otázku č.2 ?
Editoval xxxObiWan (10. 8. 2011 0:31)
- Matúš Matula
- Člen | 257
joe napsal(a):
2 – jasné, musím kontrolovat po odeslání (tedy onSuccess) a to pro každý takový formulář pak vymyslíš jméno jako název privilegia?
ano
newPOPE napsal(a):
tot moje riesenie (nikdy nepouzite, ale domnievam sa, ze ta prva vec by sla automatizovat)
mozes nacrtnut, ako by si riesil tu automatizaciu? Predsa len to ACL musis niekde nadefinovat..
- Matúš Matula
- Člen | 257
xxxObiWan: sice to nepouzivam (zatial), ale mozes napriklad rovno v konstruktore overovat, ci ma dany user povolenu danu akciu – kt. bude odvodena prave od className daneho formulara..cize to mozes pichnut do nejakeho spolocneho predka pre formulare a mas vystarane.. (aspon tak si myslim :D)
- joe
- Člen | 313
newPOPE
Každý v tom může vidět výhody i nevýhody :-) Jenom by mě zajímalo,
kam pak píšeš metody zpracování formuláře
(xxxFormSubmitted($form)
)? Pokud do presenteru, tak pak tu
autorizaci stejně musíš řešit tam, ne? Nebo to dáš třeba do konstruktoru
(jak píše Matúš Matula), ale pak zase musíš někam
ukládat ty data, co odesílal, aby o ně nepřišel, jestli se nepletu.
Matúš Matula
Jestli tomu dobře rozumim, pokud bych to udělal tak, jak jsi napsal (pak bych
musel řešit to ukládání odeslaných dat, jak jsem před chvilkou napsal),
tak bych pak zase do ACL musel připsat novou privilegii, je to tak? :)
Vlastně se mi nelíbí to, že pokud mám formulář (pro jednoduchost
s metodou GET; presenter TestPresenter) zobrazený na nějaké „akci“,
například actionDefault
, jen pro nějaké role a pak mám akci
actionFail
, tak pokud si pak adresu ručně změním na
/test/fail?do=formTest-submit
, tak formulář odešlu i přes to,
že s ním pracuji jenom v actionDefault
a actionFail
o něm není ani zmínka. Pokud by to tak nebylo, pak bych žádné
oprávnění formuláře nemusel řešit. Nejedná se o bezpečnostní
riziko?
- Filip Procházka
- Moderator | 4668
@**joe**: Jediná relativní „nevýhoda“ formulářů v oddělených třídách je, že jsou v jiném souboru. Slyšel jsem i zcestný „argument“, že programátor „nechce aby měl zasraný app třídami“.
O data ani o žádné hlouposti se starat nemusíš, protože formulář funguje úplně stejně, jako formulář v presenteru. Jenom je logicky oddělen do vlastní třídy od presenteru.
Ukázka takového formuláře:
namespace Kdyby\Application\UI;
class Form extends Nette\Application\UI\Form
{
public function __construct()
{
parent::__construct();
$this->configure();
}
protected function configure() { }
}
class UserForm extends Kdyby\Application\UI\Form
{
/** @var UsersModel */
private $users;
public function __construct(UsersModel $users)
{
parent::__construct(); // nutnost
$this->users = $users;
}
protected function configure()
{
$this->addText('name', 'Jméno');
$this->addText('surname', 'Příjmení');
$this->onSubmit[] = callback($this, 'Submitted')
}
public function Submitted()
{
// tady bude ACL a validace
$this->users->create($this->values);
}
}
Jediný tvůj argument je, že se ti to nelíbí :)
To co jsi uvedl o odesílání formuláře z jiné akce máš pravdu.
A jako bonus, protože presenter umře až na neexistující šabloně, taková
akce nemusí vůbec existovat. Můžeš klidně volat
/test/failbog?do=formTest-submit
;)
Jak se tomuhle bráním? V každém presenteru mám důsledně pouze jednu akci, pokud není nějaké další zpracování, které chci mít v jiné akci (pouze výjimky).
Editoval HosipLan (10. 8. 2011 8:21)
- joe
- Člen | 313
@HosipLan
Já nechám na každém, ať používá ten svůj způsob. Tohle bych zařadil
zrovna mezi to, o čem jsem ti odpovídal tady
Je to sice fajn, že je to logicky oddělené, ale k čemu mi to je :-) Zatím se mi málokdy stalo, že bych stejný formulář použil na více místech. Pokud už by k tomu došlo, takhle bych ho oddělil a nebo dal třeba do BasePresenteru (asi nic moc :-)) Nepoužívám to z toho důvodu, protože:
- do presenteru bych stejně psal továrničku na formulář
- mám radši, když nemusím otvírat další záložku se souborem
- mi to přijde celkem zdlouhavé, napřed nějakou třídu, od které budu dědit, pak třídu pro formulář, kde píšu konstruktor a předávám modely. Když se rozhodnu, že budu používat další model, zase to musím upravovat, přidávat si atributy apod., to mi v presenteru všechno odpadá
- budu mít ve slože app hodně tříd :))
- přidělám zbytečně práci robot loaderu
Jinak ano, pak se to všechno chová stejně. Šlo mi o to ACL, že si musím vymyslet zase název pro privilegium, to kontrolovat v onSuccess a přidat ho (staticky) do toho ACL. To je taky věc, kterou moc nemusím, proto jsem to dřív nepoužíval – protože nevidím z metody hned, kdo k ní má přístup. A po dokončení aplikace musim zkontrolovat, jestli sedí názvy zdrojů/akcí v presenterech a v ACL a všechno si to prostě ohlídat. A když vytvořím novou akci, hned zase musím jít do ACL atd… Proto si to radši podmínkuju (zatím jsem nedělal nic moc pro více rolí, takže to nebylo tak hrozné).
S tím formulářem ještě.
A jako bonus, protože presenter umře až na neexistující šabloně, taková akce nemusí vůbec existovat.
Tohle mi teď zase nedošlo, už jsi mi to jednou někde psal. Vlastně by to mohlo být kontrolováno přímo frameworkem, ne? K čemu by měl „fungovat“ formulář jinde (po přidání ?do=form-submit), než tam, kam je směřován? Nějak na to nemůžu přijít, proč to není nějak zablokované, ale dal by se k tomu využít ChangeTracker
- newPOPE
- Člen | 648
@Matúš Matula
No keby na to doslo, tak by som to riesil asi nejak takto. Mam komponenty
(Controls, Forms, etc…) to by boli resources, kazda ma nejake
akcie Control
ma render*
, Form
zase
render
, submit
, click*
…
A uz len nastavim role, a ked tak rozmyslam tak by to zrejme u mna riesila sluzba (som komponenta tu ma mas, tu mas usera a povedz mi ci ma k tomu pristup alebo nie).
Ale ako hovorim, mam to len v hlave. Cize ci je to realne netusim ;-) (no paci sa mi to)
- Filip Procházka
- Moderator | 4668
joe napsal(a):
Je to sice fajn, že je to logicky oddělené, ale k čemu mi to je :-) …
Znovupoužitelnost, když děláš na větší aplikaci, jsi pak neskutečně vděčný, za každou ušetřenou komponentu. Já je dělím ještě na jednotlivé Containery, z nich pak skládám formuláře.
- do presenteru bych stejně psal továrničku na formulář
ano to psal, měla by cca 4 řádky.
- mám radši, když nemusím otvírat další záložku se souborem
to je ale jenom tvoje lenost :)
- mi to přijde celkem zdlouhavé, napřed nějakou třídu, od které budu dědit, pak třídu pro formulář, kde píšu konstruktor a předávám modely. Když se rozhodnu, že budu používat další model, zase to musím upravovat, přidávat si atributy apod., to mi v presenteru všechno odpadá
Ano máš pravdu, můj přístup je založen striktně na Dependency
Injection. A ten BaseForm je tam proto, že metoda configure
se mi
líbí a vypadá to lépe než v konstruktoru :)
- budu mít ve slože app hodně tříd :))
:))
- přidělám zbytečně práci robot loaderu
Žádné flákání! :)
Jinak ano, pak se to všechno chová stejně. Šlo mi o to ACL, …
Většinu z toho co jsi napsal můžeš zautomatizovat, nebo je to otázka dvou kliknutí, pokud máš hotový nějaký backend základ.
Vlastně by to mohlo být kontrolováno přímo frameworkem, ne? K čemu by měl „fungovat“ formulář jinde, než tam, kam je směřován?
Mohlo, ale není. S někým jsem to řešil na Jabber #nette chatu, jak to udělat pěkně pomocí annotací. Další věc je, že pokud to nikomu do teď nevadilo, znamená to, že
- má buď aplikaci napsanou robustně a kontroluje ve zpracování formuláře, jestli má uživatel právo provést co provádí a je mu jedno, jestli si adresu sesmolil sám v address baru, nebo klikl na odkaz
- nebo to má zblastlené
Editoval HosipLan (10. 8. 2011 11:10)
- joe
- Člen | 313
@22 Anotace jsem v tý rychlosti zapomněl zmínit, vlastně jsem myslel, že ve frameworku ještě nejsou a teď ani nevím jak to s nimi je. Taky jsou dobré, ale zase je to jako komentář, lehce se to přehlídne :-) Nakonec to asi vyřeším voláním jednoduché metody všude tam, kde chci mít kontrolu oprávnění → zautomatizování je super, ale co když bych chtěl při každé kontrole provést v každé metodě (v případě neúspěchu) pokaždé trochu něco jinýho?
To například používám při AJAXu, nevyužívám žádný JS framework a
pokud potřebuji, pošlu si do payloadu callback, tzn. metodu, která se mi
v JavaScriptu provede.
(K čemu je to dobré? Je to například taková náhrada za livequery
z jQuery – že při změně znovu zAJAXovatím odkazy, přesunu flash
zprávičky tam, kam potřebuju, inicializuji znovu nějaký blok, nastavím
způsob přidávání elementů při stránkování apod.)
HosipLan
Znovupoužitelnost, když děláš na větší aplikaci, jsi pak neskutečně vděčný, za každou ušetřenou komponentu.
Líbit se ti to nebude :) ale jaký je rozdíl mezi tím, že zkopíruju do
jiného projektu komponentu a nebo kus kódu z jednoho presenteru do presenteru
v novém projektu? V tom druhém případě to budu mít ještě rychlejší,
protože nebudu muset nikde nic nastavovat a zkopíruju kus hotového kódu,
který funguje. Ve tvém případě musím komponentu nějak nastavit (tzn.
zkopírovat komponentu, zkopírovat kód pro nastavení).
Zatím jsem dělal spíš takové věci, které by se asi jinde nedaly moc
využít.
ano to psal, měla by cca 4 řádky.
Měla, ale při používání code folding by měly obě jen jeden :)
- 22
- Člen | 1478
@joe: https://api.nette.org/…lection.html – klidně si udělej svoji anotaci @mysecurity blabla1 blabla2