Fórum Root.cz

Práce => Studium a uplatnění => Téma založeno: Arthon 15. 04. 2019, 13:28:44

Název: Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 15. 04. 2019, 13:28:44
Zdravím,
mám sehnaného vedoucího práce, který by mi vedl bakalářku v tomhle směru. Ale problém je, že mě nenapadá nějaké zajímavá aplikace ve springu (mvc, security, hibernate atd)  + javascriptu. Zřejmě bych použil i REST s AJAXem, nicméně přesné zadání mě úplně nenapadá...

Jediné, co mě napadlo je - převod desktopové aplikace na webové v javě - to znamená udělat desktopovou verzi, webovou, možnosti přenosu, zabezpečení atd...

Napadlo by vás něco prosím, nějaké téma, aplikace související s tímhle tématem?

Díky moc
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 15. 04. 2019, 17:53:27
Různé spolky, které mají jednotky až desítky členů, obvykle potřebují vést evidenci svých členů spolu s kontaktními údaji a často pak potřebují svým členům po přihlášení poskytnou něco z následujícího:


Pokud má spolek ve svých řadách nějakého programátora, obvykle na to udělá nějakou webovou aplikaci, která splní minimum toho, co je potřeba. Takže takových aplikací budou po republice desítky, místo aby byl jedna dotažená a open-source, kterou si každý přizpůsobí podle svých potřeb. A nebo se to řeší různými tabulkami posílanými e-mailem, Google tabulkou, Doodle apod.

Tak můžete začít s tou opensource aplikací, ke které se později budou moci připojit ostatní :-)

Protože má zároveň každý jiné požadavky, bylo by fajn, kdyby to bylo postavené nad zdokumentovaným RESTovým rozhraním, aby se na to případně daly napojovat další systémy. Mělo by to být multitenant, aby se to na jednom serveru dalo provozovat pro víc spolků. Může tam být implementováno přihlašování pomocí OAuth 2.0 (Facebook, Google, MojeID atd.) A různých dalších vylepšení se tam dá navymýšlet spousta.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 15. 04. 2019, 19:22:59
Různé spolky, které mají jednotky až desítky členů, obvykle potřebují vést evidenci svých členů spolu s kontaktními údaji a často pak potřebují svým členům po přihlášení poskytnou něco z následujícího:

  • Zobrazit kontaktní údaje ostatních členů (e-mail, telefon, Facebook, poštovní adresa…).
  • Umožnit členům přihlásit se na nějakou spolkovou akci.
  • Nechat členy hlasovat třeba o termínu akce nebo barvě triček.
  • Vyexportovat seznam členů nebo jen některé údaje (třeba jen seznam e-mailů) do Excelu, CSV, vytisknout prezenční listinu všech členů nebo jen těch přihlášených na akci (vygenerovat PDF).
  • Rozeslat členům e-mail na základě nějaké šablony (třeba s platebními údaji).

Pokud má spolek ve svých řadách nějakého programátora, obvykle na to udělá nějakou webovou aplikaci, která splní minimum toho, co je potřeba. Takže takových aplikací budou po republice desítky, místo aby byl jedna dotažená a open-source, kterou si každý přizpůsobí podle svých potřeb. A nebo se to řeší různými tabulkami posílanými e-mailem, Google tabulkou, Doodle apod.

Tak můžete začít s tou opensource aplikací, ke které se později budou moci připojit ostatní :-)

Protože má zároveň každý jiné požadavky, bylo by fajn, kdyby to bylo postavené nad zdokumentovaným RESTovým rozhraním, aby se na to případně daly napojovat další systémy. Mělo by to být multitenant, aby se to na jednom serveru dalo provozovat pro víc spolků. Může tam být implementováno přihlašování pomocí OAuth 2.0 (Facebook, Google, MojeID atd.) A různých dalších vylepšení se tam dá navymýšlet spousta.

děkuji za pěknou inspiraci. Mohl byste, prosím, rozvinout tu druhou část? Mohl byste mi vysvětlit, jak si představujete tu část s RESTEM? A to s multitenant - "aby se to na jednom serveru dalo provozovat pro víc spolků" - to znamená, že bude jeden server, jedna databáze, do které se budou ukládat všechny ty spolky, informace a další data...
Tedy prakticky: Byl by napsán server ve springu s REST, a potencionální uživatelé by používali tu klientskou část, která by přes AJAX stahovala data ze serveru, že? S tím, že několik spolků může být spravováno v jeden čas.
Díky
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: registrovany_ava 15. 04. 2019, 20:29:29
registr ohnǒstrojů https://forum.root.cz/index.php?topic=10339.0 (https://forum.root.cz/index.php?topic=10339.0)
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 15. 04. 2019, 21:46:43
děkuji za pěknou inspiraci. Mohl byste, prosím, rozvinout tu druhou část? Mohl byste mi vysvětlit, jak si představujete tu část s RESTEM? A to s multitenant - "aby se to na jednom serveru dalo provozovat pro víc spolků" - to znamená, že bude jeden server, jedna databáze, do které se budou ukládat všechny ty spolky, informace a další data...
Tedy prakticky: Byl by napsán server ve springu s REST, a potencionální uživatelé by používali tu klientskou část, která by přes AJAX stahovala data ze serveru, že? S tím, že několik spolků může být spravováno v jeden čas.
Díky
Psal jste, že byste použil REST s AJAXem. To zapadá do mé představy, jakou by taková aplikace měla mít architekturu – na backendu Spring, který bude veškeré služby poskytovat přes RESTové API, a jako frontend klasická SPA, která bude volat to RESTové API. Mně by se pro tu frontend část nejvíce líbilo Vue, ale klidně to může být třeba Angular nebo React.

Má poznámka k RESTu pak směřovala k tomu, aby to RESTové API bylo navržené tak, že může fungovat i samostatně, bez té webové aplikace. Často se totiž stává, že když se navrhuje RESTOvé API pro jednu konkrétní SPA, je to API s tou frontendovou aplikací natolik svázané, že prakticky nejde jinde použít. Tady by ale myslím bylo vhodné, aby cokoli, co půjde udělat přes webový frontend, šlo (bez větší námahy) udělat i voláním API. Například klasický postup přidání nového člena spolku by byl takový, že to nějaký administrátor spolku nakliká přes webové rozhraní. Ale spolek už má třeba jinou evidenci a chtěl by používat jiné funkce té aplikace – tak si udělá propojku, která přes to RESTové API bude vytvářet členy na základě toho druhého systému.

Multitenant znamená, že se aplikace provozuje jenom jednou (typicky jen s jednou databází), ale z hlediska uživatelů se to chová, jako kdyby to bylo víc nezávislých aplikací, pro každý spolek jiná. Např. můžete mít jednu instalaci účetního programu, vede se v ní ale účetnictví několika firem. Z pohledu uživatelů se to chová, jako by účetnictví každé firmy bylo zvlášť – nesmí se tedy stát, že by účetní jedné firmy viděl nějaké údaje z jiné firmy, nebo že by si i navzájem mohli jenom měnit konfiguraci.

Nejsnazší by samozřejmě bylo mít pro každou firmu/spolek jinou databázi, jenže to je zejména ve webovém prostředí obtížně řešitelné – pokud byste měl na jednom serveru třeba 100 databází, těžko může server udržovat třeba 400 spojení do databáze (pro každou databázi 4), která by byla většinu času neaktivní. Druhá možnost je mít vše ve společných tabulkách, prakticky v každé tabulce pak tedy musí být i sloupec určující, do které firmy daný záznam patří. Pak je samozřejmě potřeba ve všech dotazech přidávat i podmínku na aktuální firmu, aby se právě nestalo, že se někde zobrazí i údaje někoho jiného. To je jedna nevýhoda, druhá nevýhoda je, že se pak jednotlivé firmy ovlivňují více, než je zdrávo – když budete mít devět firem, každá bude mít deset faktur, a desátá firma bude mít deset tisíc faktur, penalizované za to, že pracují s tabulkou o desetitisíci záznamech (což je tedy pořád málo, ale v jiných tabulkách může být těch záznamů řádově víc), budou všechny firmy. Většina relačních databází pak umožňuje ještě něco mezi, že se připojujete k jedné databázi, ale uvnitř ní je víc prostorů, které jsou do jisté míry oddělené. Třeba v PostgreSQL by se pro tohle dala použít schémata.

Ale zároveň to není věc, která by tam musela být za každou cenu hned od začátku, asi to není věc, která by se řešila na úrovni bakalářské práce. Ale dá se s tím počítat třeba na úrovni API – třeba účetnictví Flexibee to má dělané tak, že první položka cesty v URL je vždy identifikátor firmy. Takže třeba pro seznam faktur Firmy1 voláte https://www.example.com/firma1/faktury a pro seznam faktur Firmy dva voláte https://www.example.com/firma2/faktury. Mimochodem zrovna Flexibee má docela pěkné API, ve kterém jde udělat skoro všechno, co umí ta aplikace samotná.

Pokud byste měl nějaké další dotazy, klidně se ptejte. Já budu rád, když taková aplikace konečně vznikne a nebudu jí muset příště psát znova sám :-)
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Zdenek Henek 16. 04. 2019, 09:07:42
děkuji za pěknou inspiraci. Mohl byste, prosím, rozvinout tu druhou část? Mohl byste mi vysvětlit, jak si představujete tu část s RESTEM? A to s multitenant - "aby se to na jednom serveru dalo provozovat pro víc spolků" - to znamená, že bude jeden server, jedna databáze, do které se budou ukládat všechny ty spolky, informace a další data...
Tedy prakticky: Byl by napsán server ve springu s REST, a potencionální uživatelé by používali tu klientskou část, která by přes AJAX stahovala data ze serveru, že? S tím, že několik spolků může být spravováno v jeden čas.
Díky
Psal jste, že byste použil REST s AJAXem. To zapadá do mé představy, jakou by taková aplikace měla mít architekturu – na backendu Spring, který bude veškeré služby poskytovat přes RESTové API, a jako frontend klasická SPA, která bude volat to RESTové API. Mně by se pro tu frontend část nejvíce líbilo Vue, ale klidně to může být třeba Angular nebo React.

Má poznámka k RESTu pak směřovala k tomu, aby to RESTové API bylo navržené tak, že může fungovat i samostatně, bez té webové aplikace. Často se totiž stává, že když se navrhuje RESTOvé API pro jednu konkrétní SPA, je to API s tou frontendovou aplikací natolik svázané, že prakticky nejde jinde použít. Tady by ale myslím bylo vhodné, aby cokoli, co půjde udělat přes webový frontend, šlo (bez větší námahy) udělat i voláním API. Například klasický postup přidání nového člena spolku by byl takový, že to nějaký administrátor spolku nakliká přes webové rozhraní. Ale spolek už má třeba jinou evidenci a chtěl by používat jiné funkce té aplikace – tak si udělá propojku, která přes to RESTové API bude vytvářet členy na základě toho druhého systému.

Multitenant znamená, že se aplikace provozuje jenom jednou (typicky jen s jednou databází), ale z hlediska uživatelů se to chová, jako kdyby to bylo víc nezávislých aplikací, pro každý spolek jiná. Např. můžete mít jednu instalaci účetního programu, vede se v ní ale účetnictví několika firem. Z pohledu uživatelů se to chová, jako by účetnictví každé firmy bylo zvlášť – nesmí se tedy stát, že by účetní jedné firmy viděl nějaké údaje z jiné firmy, nebo že by si i navzájem mohli jenom měnit konfiguraci.

Nejsnazší by samozřejmě bylo mít pro každou firmu/spolek jinou databázi, jenže to je zejména ve webovém prostředí obtížně řešitelné – pokud byste měl na jednom serveru třeba 100 databází, těžko může server udržovat třeba 400 spojení do databáze (pro každou databázi 4), která by byla většinu času neaktivní. Druhá možnost je mít vše ve společných tabulkách, prakticky v každé tabulce pak tedy musí být i sloupec určující, do které firmy daný záznam patří. Pak je samozřejmě potřeba ve všech dotazech přidávat i podmínku na aktuální firmu, aby se právě nestalo, že se někde zobrazí i údaje někoho jiného. To je jedna nevýhoda, druhá nevýhoda je, že se pak jednotlivé firmy ovlivňují více, než je zdrávo – když budete mít devět firem, každá bude mít deset faktur, a desátá firma bude mít deset tisíc faktur, penalizované za to, že pracují s tabulkou o desetitisíci záznamech (což je tedy pořád málo, ale v jiných tabulkách může být těch záznamů řádově víc), budou všechny firmy. Většina relačních databází pak umožňuje ještě něco mezi, že se připojujete k jedné databázi, ale uvnitř ní je víc prostorů, které jsou do jisté míry oddělené. Třeba v PostgreSQL by se pro tohle dala použít schémata.

Ale zároveň to není věc, která by tam musela být za každou cenu hned od začátku, asi to není věc, která by se řešila na úrovni bakalářské práce. Ale dá se s tím počítat třeba na úrovni API – třeba účetnictví Flexibee to má dělané tak, že první položka cesty v URL je vždy identifikátor firmy. Takže třeba pro seznam faktur Firmy1 voláte https://www.example.com/firma1/faktury a pro seznam faktur Firmy dva voláte https://www.example.com/firma2/faktury. Mimochodem zrovna Flexibee má docela pěkné API, ve kterém jde udělat skoro všechno, co umí ta aplikace samotná.

Pokud byste měl nějaké další dotazy, klidně se ptejte. Já budu rád, když taková aplikace konečně vznikne a nebudu jí muset příště psát znova sám :-)

Co se týče tenatizace, tak je ještě možnost mít jedno schema pro metadata a sdílet všechny tabulky a pro vlastní data tabulku zvlášť.
Důvodem je, že pokud budete mít tisíce zákazníků, tak si nedokážu moc dobře představit udržbu nebo upgrade tisíce schemat v databázi.

Jedno schema pro metadata a jedno pro data. Metadata je například nastavení uživatele a informace o něm. Metadata všech tenantů sdílí tabulky. Data všech tenantů do jednoho dalšího schemata. Například pokud budete řešit faktury za dany rok, tak by každý tenant měl jednu tabulku na každý rok.

Pro sdílená data mezi všemi tenanty máme ještě třetí schema. 

Veškeré datové objekty doporučuji mít immutable a pro výkon by mohlo pomoct mít metadata uložena v cache, například Caffeine
https://github.com/ben-manes/caffeine

V cache může být jen objekt a klíčem bude id toho objektu, nebo v další cache může být i seznam id ze selektu. Záleží jak moc chcete řešit problémy cache.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Andrej Kvasnica 17. 04. 2019, 13:20:49
Sprav webovy soft na vizualizaciu rozvrhov pre multitrack konferencie:

V prvej verzii by uplne stacil hlupy editor, v dalsej verzii mozes pridat viac dni, potom by to mohlo mat aj nejaku inteligenciu (zgrupovanie kratkych prednasok kvoli minimalizacii prestojov) az po megafunkcie ako zistovanie zaujmu skupiny ludi o konkretne prednasky a nasledny rozvrh maximalne uspokojujuci celu skupinu minimalizaciou prekryvov najziadanejsich prednasok.

Vystup cez export do HTML s vizualizaciou trackou vedla seba a so zobrazenim dlzky jednotlivych prednasok.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: PetrK 17. 04. 2019, 13:50:37
Kdybych dnes chodil na VS a delal bakalarku nebo diplomku, tak se zamerim na perfromance testy. Udelal bych testovaci apliakci ktera porovnava v nejakem smysluplnem scenari perfromanceHibernate a treba myBatis. Nebo se zameruje na ladeni Hibernate. V praxi kdyz se pouziva hibernate tak jsou s tim vykonostni potize.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: PetrK 17. 04. 2019, 14:37:23
Kdybych dnes chodil na VS a delal bakalarku nebo diplomku, tak se zamerim na perfromance testy. Udelal bych testovaci apliakci ktera porovnava v nejakem smysluplnem scenari perfromanceHibernate a treba myBatis. Nebo se zameruje na ladeni Hibernate. V praxi kdyz se pouziva hibernate tak jsou s tim vykonostni potize.

Vyhoda je, ze tim delas opravdu nejaky obecny vyzkum, namisto toho, aby jsi na VS delal nejakou nesmyslnou aplikaci, treba pro ty konference. Protoze bezesporu ta aplikace co udelas bude beztak stat za govno, takhle alespon budes mit vysledky mereni.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: PetrK 18. 04. 2019, 08:32:55
Me by treba zajimalo, jakou bude mit Hibernate v zakladni konfiguraci perfromance pro zretezeny eager fetch tabulek T1...Tn oproti tomu samemu napsanemu pomoci plain SQL, a jaky performance bude mit opakovani toho dotazu (hibernate  cachuje). Plus nejake dalsi simulovane use case.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Andrej Kvasnica 18. 04. 2019, 09:23:30
Kdybych dnes chodil na VS a delal bakalarku nebo diplomku, tak se zamerim na perfromance testy. Udelal bych testovaci apliakci ktera porovnava v nejakem smysluplnem scenari perfromanceHibernate a treba myBatis. Nebo se zameruje na ladeni Hibernate. V praxi kdyz se pouziva hibernate tak jsou s tim vykonostni potize.
Vyhoda je, ze tim delas opravdu nejaky obecny vyzkum, namisto toho, aby jsi na VS delal nejakou nesmyslnou aplikaci, treba pro ty konference. Protoze bezesporu ta aplikace co udelas bude beztak stat za govno, takhle alespon budes mit vysledky mereni.
Jaska, nezmyselna appka napriklad na tie konfery je somarina co sa neda rozvijat. Aj Zuck alebo Page/Brin robili statistiky okolo ORM mapovania a pekne tu myslienku rozvijaju az doteraz.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: gill 18. 04. 2019, 10:01:04
Me by treba zajimalo, jakou bude mit Hibernate v zakladni konfiguraci perfromance pro zretezeny eager fetch tabulek T1...Tn oproti tomu samemu napsanemu pomoci plain SQL, a jaky performance bude mit opakovani toho dotazu (hibernate  cachuje). Plus nejake dalsi simulovane use case.

Na tom nic nevyzkoumas. To zalezi na nastaveni cachovani. Ciste SQL muzes take cachovat, i v aplikaci.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: izavec 18. 04. 2019, 10:29:35
studoval som v dansku a tam to pre studentov softaware engineeringu byva takto: najdu si firmu pre ktoru vybuduju realny produkt. je celkom caste ze student popri skole uz aj niekde robi a ked nema vlastny napad, manazeri vedia vzdy nieco najst...vyhodou je, ze by si mohol vytvorit nieco co (ak sa podari) vytvori nejaku realnu hodnotu a bude nadalej zit. moznoze sa aj pohras s CI/CD...

ja som napriklad robil (v spolupraci s dalsim spoluziakom) dashboard(angular + net core api) na monitoring vykonu nejakeho (uz existujuceho) ML systemu...

Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: PetrK 19. 04. 2019, 09:15:25
Me by treba zajimalo, jakou bude mit Hibernate v zakladni konfiguraci perfromance pro zretezeny eager fetch tabulek T1...Tn oproti tomu samemu napsanemu pomoci plain SQL, a jaky performance bude mit opakovani toho dotazu (hibernate  cachuje). Plus nejake dalsi simulovane use case.

Na tom nic nevyzkoumas. To zalezi na nastaveni cachovani. Ciste SQL muzes take cachovat, i v aplikaci.

Jak ze na tom nic nevyzkoumas, to si delas srandu ne. Zrovna ohledne cachovani o kterem pises muzes porovnat perfromance SQL a Hibernate kdyz ma databaze delays ze je jakoze remote a kdyz je databaze na stejnem stroji. Databaze si taky umi cachovat, takze nepotrebujes mit cache 2x, paklize jede ta DB na stejne masine.

Uz i samotne na tom nic nevyzkoumas je hlod, vsude se delaji enterprise informacni systemy a tomuhle malokdo dobre rozumi.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 19. 04. 2019, 09:48:26
Jak ze na tom nic nevyzkoumas, to si delas srandu ne. Zrovna ohledne cachovani o kterem pises muzes porovnat perfromance SQL a Hibernate kdyz ma databaze delays ze je jakoze remote a kdyz je databaze na stejnem stroji. Databaze si taky umi cachovat, takze nepotrebujes mit cache 2x, paklize jede ta DB na stejne masine.
Co na tom vyzkoumáte jiného, než síťový round-trip databáze?

Uz i samotne na tom nic nevyzkoumas je hlod, vsude se delaji enterprise informacni systemy a tomuhle malokdo dobre rozumi.
Co na tom tedy vyzkoumá užitečného? Tedy takového, co bude platit i pro jiné případy, než pro ten jeden, který zkoumal? V reálném světě je každý systém jiný a chová se jinak. Chování se mění i v závislosti na tom, kolik je zrovna aktivních uživatelů a co dělají. A zrovna u enterprise informačních systémů se milisekundy zpoždění síťové odezvy při přístupu do databáze opravdu neřeší. Navíc u enterprise systému by snad nikoho nenapadlo provozovat aplikační server a databázi na tom samém stroji.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: PetrK 19. 04. 2019, 12:13:14
Jak ze na tom nic nevyzkoumas, to si delas srandu ne. Zrovna ohledne cachovani o kterem pises muzes porovnat perfromance SQL a Hibernate kdyz ma databaze delays ze je jakoze remote a kdyz je databaze na stejnem stroji. Databaze si taky umi cachovat, takze nepotrebujes mit cache 2x, paklize jede ta DB na stejne masine.
Co na tom vyzkoumáte jiného, než síťový round-trip databáze?

Uz i samotne na tom nic nevyzkoumas je hlod, vsude se delaji enterprise informacni systemy a tomuhle malokdo dobre rozumi.
Co na tom tedy vyzkoumá užitečného? Tedy takového, co bude platit i pro jiné případy, než pro ten jeden, který zkoumal? V reálném světě je každý systém jiný a chová se jinak. Chování se mění i v závislosti na tom, kolik je zrovna aktivních uživatelů a co dělají. A zrovna u enterprise informačních systémů se milisekundy zpoždění síťové odezvy při přístupu do databáze opravdu neřeší. Navíc u enterprise systému by snad nikoho nenapadlo provozovat aplikační server a databázi na tom samém stroji.

Dyt tam se toho da vyzkouset tolik.

Napr. rozjet Postgresql lokalne a pouzit Hibernate pro praci s entitami, bez pouziti second level cache. Pak zkusit nasimulovat delay do te databaze a zapnout second level cache a porovnat vysledek. Potom zkusit zapnout diskPersitence u te cache a porovnat vysledek. Ucelem toho mereni je, porovnat performance cache kterou ma Hibernate v Jave a kterou by melo Postrgesql. A ty prerformance testy udelat poradne, simulovat treba 100 paralelnich requestu za vterinu.

Citace
<cache name="com.mycompany.MyEntity"
   maxElementsInMemory="50"
   eternal="true"
   overflowToDisk="false"
   timeToIdleSeconds="600"
   timeToLiveSeconds="600"
   diskPersistent="false"
   memoryStoreEvictionPolicy="LRU"       
/>

Ucelem toho vseho je doakazat, ze Hibernate a Java je sracka co akorat zere RAM a zatezuje servery 8) :D A nebo mozna prekvapi?  8)


Da se otestovat spousta zajimavych veci a kdyz se to udela poradne, tak z toho bude uzitecny vystup. Kdezto kdyz bude nekdo vyrabet jakousik webovku, tak to stejne bude stat za houby a nebude to k nicemu, akorat to skonci na skladisti bakalarek tak jako u miliony jeho predchudcu.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 19. 04. 2019, 12:37:00
tam se toho da vyzkouset tolik.
Já jsem se ale ptal, k čemu to bude.

Napr. rozjet Postgresql lokalne a pouzit Hibernate pro praci s entitami, bez pouziti second level cache. Pak zkusit nasimulovat delay do te databaze a zapnout second level cache a porovnat vysledek. Potom zkusit zapnout diskPersitence u te cache a porovnat vysledek. Ucelem toho mereni je, porovnat performance cache kterou ma Hibernate v Jave a kterou by melo Postrgesql. A ty prerformance testy udelat poradne, simulovat treba 100 paralelnich requestu za vterinu.
Ano, to se dá udělat. A zjistí výsledky, které se vztahují přesně k tomuhle jednomu testu, které ale budou k ničemu ve všech ostatních případech, např. u reálných aplikací. K čemu to tedy bude?

Ucelem toho vseho je doakazat, ze Hibernate a Java je sracka co akorat zere RAM a zatezuje servery 8) :D A nebo mozna prekvapi?  8)
Aha, tak to vysvětluje vše. Prostě máte nějaký výsledek, a teď sháníte libovolný postup, jak se k němu dostat.

Da se otestovat spousta zajimavych veci a kdyz se to udela poradne, tak z toho bude uzitecny vystup.
Aby z toho byl užitečný výstup, musel by otestovat tisíce různých kombinací aplikací, databází, způsobů zátěže a konfigurací. Ten váš příklad s cache nevypovídá vůbec o ničem, protože účinnost cache se samozřejmě bude dramaticky lišit v závislosti na formě pracovní zátěže – záleží na poměru mezi čtením a zápisem, na tom, zda se čtou opakovaně stejná data, na tom, zda je povolené poskytovat starší data.

Kdezto kdyz bude nekdo vyrabet jakousik webovku, tak to stejne bude stat za houby a nebude to k nicemu, akorat to skonci na skladisti bakalarek tak jako u miliony jeho predchudcu.
Webovou aplikaci je možné jako bakalářskou práci udělat pořádně. Vaše měření v žádném případě. Myslíte, že mu někdo pro účely bakalářské práce půjčí Exadatu, stovky gigabajtů dat a stovky uživatelů, kteří budou provádět reálnou práci? Když jste to chtěl vztahovat na enterprise informační systémy…
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: PetrK 19. 04. 2019, 12:48:06
tam se toho da vyzkouset tolik.
Já jsem se ale ptal, k čemu to bude.

A ja se zase ptam, k cemu bude nejaka nedodelana a nefungujici webova aplikace je jedno pro co, treba pro konference. Takovou aplikaci NIKDY jako jednotlivec nedotahne do pouzitelenho konce v ramci nejake pitome bakalarky, pokud nechce ztratit kus drahoceneho zivota.

Napr. rozjet Postgresql lokalne a pouzit Hibernate pro praci s entitami, bez pouziti second level cache. Pak zkusit nasimulovat delay do te databaze a zapnout second level cache a porovnat vysledek. Potom zkusit zapnout diskPersitence u te cache a porovnat vysledek. Ucelem toho mereni je, porovnat performance cache kterou ma Hibernate v Jave a kterou by melo Postrgesql. A ty prerformance testy udelat poradne, simulovat treba 100 paralelnich requestu za vterinu.
Ano, to se dá udělat. A zjistí výsledky, které se vztahují přesně k tomuhle jednomu testu, které ale budou k ničemu ve všech ostatních případech, např. u reálných aplikací. K čemu to tedy bude?

K tomuhle testu se vztahuje vysledek ve smyslu celkhoveho zatizeni pocitace u Postrges vs javovsky Hibernate. Jestli vam to prijde jako nudny a bezvyznamny test, tak to je potom problem.

Ucelem toho vseho je doakazat, ze Hibernate a Java je sracka co akorat zere RAM a zatezuje servery 8) :D A nebo mozna prekvapi?  8)
Aha, tak to vysvětluje vše. Prostě máte nějaký výsledek, a teď sháníte libovolný postup, jak se k němu dostat.
Tomu se rika udrzovat veci jednoduche a nevymyslet kraviny, ale misto toho hledat zpusoby a duvody, proc jednoduchymi muzou zustat. Javy a Hibernate se to tyka prevelice.

Da se otestovat spousta zajimavych veci a kdyz se to udela poradne, tak z toho bude uzitecny vystup.
Aby z toho byl užitečný výstup, musel by otestovat tisíce různých kombinací aplikací, databází, způsobů zátěže a konfigurací. Ten váš příklad s cache nevypovídá vůbec o ničem, protože účinnost cache se samozřejmě bude dramaticky lišit v závislosti na formě pracovní zátěže – záleží na poměru mezi čtením a zápisem, na tom, zda se čtou opakovaně stejná data, na tom, zda je povolené poskytovat starší data.

Ale prd, na to abyste otestoval dopad pouzivani Java hoven na performance nejakeho enterprise enviromentu nemusite testovat tisice ruznych kombinaci.

Kdezto kdyz bude nekdo vyrabet jakousik webovku, tak to stejne bude stat za houby a nebude to k nicemu, akorat to skonci na skladisti bakalarek tak jako u miliony jeho predchudcu.
Webovou aplikaci je možné jako bakalářskou práci udělat pořádně. Vaše měření v žádném případě. Myslíte, že mu někdo pro účely bakalářské práce půjčí Exadatu, stovky gigabajtů dat a stovky uživatelů, kteří budou provádět reálnou práci? Když jste to chtěl vztahovat na enterprise informační systémy…
[/quote]

Pokus o vyrobu webove aplikace skonci s pravdepodobnosti 1000:1 jako dalsi bakalarsky shit, kde jedinym vystupem z toho vseho budou nejake nove znalosti a zkusenosti pro toho dotycneho, ale zadny realny uzitecny vysledek pro ostatni.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 19. 04. 2019, 12:58:53
K tomuhle testu se vztahuje vysledek ve smyslu celkhoveho zatizeni pocitace u Postrges vs javovsky Hibernate.
Který je ovšem závislý na způsobu použití PostgreSQL, na způsobu použití Hibernate, a na způsobu použití dané aplikace. Jenom v tomhle jednoduchém příkladu tedy máte tři nezávislé proměnné, takže jeden test vám neřekne vůbec nic.

Navíc vy přece ani nechcete nic testovat, vy už máte o výsledku jasno.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: skybber 20. 04. 2019, 20:14:05
REST/AJAX aplikaci zvládne šikovný středoškolák. Pokud chceš proniknout hlouběji do architektury Springu, tak výborné téma je Spring Plugin pro HotswapAgent https://github.com/HotswapProjects/HotswapAgent/tree/master/plugin/hotswap-agent-spring-plugin
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: PetrK 20. 04. 2019, 21:18:58
REST/AJAX aplikaci zvládne šikovný středoškolák. Pokud chceš proniknout hlouběji do architektury Springu, tak výborné téma je Spring Plugin pro HotswapAgent https://github.com/HotswapProjects/HotswapAgent/tree/master/plugin/hotswap-agent-spring-plugin

Hotswap Agent je na kolene ubastleny utter crap a doufam ze ho nikde v zadnem projektu konfigurovany neuvidim, protoze je to typicke polofunkcni DODO ktere akorat zvedne codabase a starosti programatorum.

Jedine DCEVM a na Spring Boot uz Hotswap Agenta stejne nepotrebujes, protoze se to umi vcelku svizne reloadnout.

Jinak kdyz uz jsme tady tak krasne resili Javu, Spring  a dostali jsme se k Hotswap, tak se mi vcelku libi jak ma Hotswap vyreseno golang - nijak. Nez totiz ta plecka Java s pomalym Springem nastartuje, tak aplikace v Go uz by mezitim nabehla 100x.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: skybber 21. 04. 2019, 08:25:35
Prave, kdyby nebylo v HotswapAgentovi co zlepsovat, tak to sem nepisu. Jinak zvedne code base? To myslis vazne nebo nevis o cem pises?
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: PetrK 21. 04. 2019, 10:44:07
Prave, kdyby nebylo v HotswapAgentovi co zlepsovat, tak to sem nepisu. Jinak zvedne code base? To myslis vazne nebo nevis o cem pises?

Ten Hotswap agent nefunguje ani nahodou out of box, musi se nakonfigurovat, pripadne se mu tam musi rucne pridat a naprogramovat ty jeho handlery, aby hotswap na ruzne pouzite technologie fungoval. Takze ano, zvedne to codebase.

Navic uz existuje JRebel, ktery to dela mnohem lepe.

A navic to ani neni potreba, protoze Spring Boot uz se resfreshnout dokaze.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: skybber 21. 04. 2019, 15:41:22
Po HotswapAgentovi nemůžete chtít zázraky, jako je reload Vašeho proprietárního frameworku. Na jednoduchoučké aplikace, ktere bootuji pár sekund to nedává smysl, jak píšete. Určitě víte, že srovnání s  JRebel z různých důvodů je taktéž nesmyslné... Autor původního dotazu hledá téma pro bakalářskou práci ve Spring. Spring plugin v HotswapAgentovi vyžaduje znalost mechanismu konfigurace, dynamické CGLIB proxy a ruzných Spring keší, zkrátka  je to dobrá cesta nezůstat někde na povrchu, ale dostat se hlouběji do mechanismů práce Java frameworků.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: PetrK 25. 04. 2019, 09:05:00
Po HotswapAgentovi nemůžete chtít zázraky, jako je reload Vašeho proprietárního frameworku. Na jednoduchoučké aplikace, ktere bootuji pár sekund to nedává smysl, jak píšete. Určitě víte, že srovnání s  JRebel z různých důvodů je taktéž nesmyslné... Autor původního dotazu hledá téma pro bakalářskou práci ve Spring. Spring plugin v HotswapAgentovi vyžaduje znalost mechanismu konfigurace, dynamické CGLIB proxy a ruzných Spring keší, zkrátka  je to dobrá cesta nezůstat někde na povrchu, ale dostat se hlouběji do mechanismů práce Java frameworků.

Jo to mate pravdu, ze z hlediska nabytych zkusenosti to bude stat za to. Ja rozporuju spise uzitecnost toho agenta v dnesni dobe. A taky neco jsem si s nim zazil.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 26. 04. 2019, 19:33:21
děkuji za pěknou inspiraci. Mohl byste, prosím, rozvinout tu druhou část? Mohl byste mi vysvětlit, jak si představujete tu část s RESTEM? A to s multitenant - "aby se to na jednom serveru dalo provozovat pro víc spolků" - to znamená, že bude jeden server, jedna databáze, do které se budou ukládat všechny ty spolky, informace a další data...
Tedy prakticky: Byl by napsán server ve springu s REST, a potencionální uživatelé by používali tu klientskou část, která by přes AJAX stahovala data ze serveru, že? S tím, že několik spolků může být spravováno v jeden čas.
Díky
Psal jste, že byste použil REST s AJAXem. To zapadá do mé představy, jakou by taková aplikace měla mít architekturu – na backendu Spring, který bude veškeré služby poskytovat přes RESTové API, a jako frontend klasická SPA, která bude volat to RESTové API. Mně by se pro tu frontend část nejvíce líbilo Vue, ale klidně to může být třeba Angular nebo React.

Má poznámka k RESTu pak směřovala k tomu, aby to RESTové API bylo navržené tak, že může fungovat i samostatně, bez té webové aplikace. Často se totiž stává, že když se navrhuje RESTOvé API pro jednu konkrétní SPA, je to API s tou frontendovou aplikací natolik svázané, že prakticky nejde jinde použít. Tady by ale myslím bylo vhodné, aby cokoli, co půjde udělat přes webový frontend, šlo (bez větší námahy) udělat i voláním API. Například klasický postup přidání nového člena spolku by byl takový, že to nějaký administrátor spolku nakliká přes webové rozhraní. Ale spolek už má třeba jinou evidenci a chtěl by používat jiné funkce té aplikace – tak si udělá propojku, která přes to RESTové API bude vytvářet členy na základě toho druhého systému.

Multitenant znamená, že se aplikace provozuje jenom jednou (typicky jen s jednou databází), ale z hlediska uživatelů se to chová, jako kdyby to bylo víc nezávislých aplikací, pro každý spolek jiná. Např. můžete mít jednu instalaci účetního programu, vede se v ní ale účetnictví několika firem. Z pohledu uživatelů se to chová, jako by účetnictví každé firmy bylo zvlášť – nesmí se tedy stát, že by účetní jedné firmy viděl nějaké údaje z jiné firmy, nebo že by si i navzájem mohli jenom měnit konfiguraci.

Nejsnazší by samozřejmě bylo mít pro každou firmu/spolek jinou databázi, jenže to je zejména ve webovém prostředí obtížně řešitelné – pokud byste měl na jednom serveru třeba 100 databází, těžko může server udržovat třeba 400 spojení do databáze (pro každou databázi 4), která by byla většinu času neaktivní. Druhá možnost je mít vše ve společných tabulkách, prakticky v každé tabulce pak tedy musí být i sloupec určující, do které firmy daný záznam patří. Pak je samozřejmě potřeba ve všech dotazech přidávat i podmínku na aktuální firmu, aby se právě nestalo, že se někde zobrazí i údaje někoho jiného. To je jedna nevýhoda, druhá nevýhoda je, že se pak jednotlivé firmy ovlivňují více, než je zdrávo – když budete mít devět firem, každá bude mít deset faktur, a desátá firma bude mít deset tisíc faktur, penalizované za to, že pracují s tabulkou o desetitisíci záznamech (což je tedy pořád málo, ale v jiných tabulkách může být těch záznamů řádově víc), budou všechny firmy. Většina relačních databází pak umožňuje ještě něco mezi, že se připojujete k jedné databázi, ale uvnitř ní je víc prostorů, které jsou do jisté míry oddělené. Třeba v PostgreSQL by se pro tohle dala použít schémata.

Ale zároveň to není věc, která by tam musela být za každou cenu hned od začátku, asi to není věc, která by se řešila na úrovni bakalářské práce. Ale dá se s tím počítat třeba na úrovni API – třeba účetnictví Flexibee to má dělané tak, že první položka cesty v URL je vždy identifikátor firmy. Takže třeba pro seznam faktur Firmy1 voláte https://www.example.com/firma1/faktury a pro seznam faktur Firmy dva voláte https://www.example.com/firma2/faktury. Mimochodem zrovna Flexibee má docela pěkné API, ve kterém jde udělat skoro všechno, co umí ta aplikace samotná.

Pokud byste měl nějaké další dotazy, klidně se ptejte. Já budu rád, když taková aplikace konečně vznikne a nebudu jí muset příště psát znova sám :-)

Zdravím,
potřeboval bych k tomu ještě vymyslet pořádné zabezpečení té aplikace. Napadlo by Vás něco, co by se dalo (z toho balíčku security) implementovat? Respektive co by ta aplikace měla mít, aby byla opravdu bezpečná?
Samozřejmostí by mělo být https a šifrovaná hesla - nicméně:
Pokud bych používal REST api, tak https na straně springu těžko nastavím, že?
Co jiného, kromě https a šifrování hesla by se k tomu dalo přidat?

Děkuji
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Ondrej Nemecek 26. 04. 2019, 20:39:51
Zdravím,
potřeboval bych k tomu ještě vymyslet pořádné zabezpečení té aplikace. Napadlo by Vás něco, co by se dalo (z toho balíčku security) implementovat? Respektive co by ta aplikace měla mít, aby byla opravdu bezpečná?
Samozřejmostí by mělo být https a šifrovaná hesla - nicméně:
Pokud bych používal REST api, tak https na straně springu těžko nastavím, že?
Co jiného, kromě https a šifrování hesla by se k tomu dalo přidat?

Bezpečné na jaké vrstvě? Můžete použít třeba klientské certifikáty. Https je sice spíše věc aplikačního serveru, ale IMHO lze propojit s aplikační logikou i ve Spring REST. Vzal bych nicméně v úvahu taky jednoduchost nasazení apod. - abyste nešel s kanónem na vrabce. Inspirujte se u jiných služeb. Řada bankovnictví má jen https a heslo, pak je to OpenID a alternativy.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 26. 04. 2019, 22:18:50
Zdravím,
potřeboval bych k tomu ještě vymyslet pořádné zabezpečení té aplikace. Napadlo by Vás něco, co by se dalo (z toho balíčku security) implementovat? Respektive co by ta aplikace měla mít, aby byla opravdu bezpečná?
Samozřejmostí by mělo být https a šifrovaná hesla - nicméně:
Pokud bych používal REST api, tak https na straně springu těžko nastavím, že?
Co jiného, kromě https a šifrování hesla by se k tomu dalo přidat?

Děkuji
Průmyslový standard pro takovéhle aplikace je dnes OAuth2. Uživatel se přihlásí a na straně té webové aplikace (v prohlížeči) pak má zapamatovaný JSON token (JWT), který se následně přibaluje ke každému RESTovému požadavku. Frameworky pro SPA pro to už obvykle mají nějakou podporu, jenom JWT tomu frameworku předáte a on už ho pak automaticky přidává do hlaviček každého požadavku.
Přihlášení se pak dá udělat přes „sociální“ sítě (Google, Facebook, Twitter, GitHub) nebo přes OpenID, aby si uživatel nemusel vytvářet další účet. Pořád ale bude potřeba fallback, aby si uživatel mohl vytvořit i klasický účet se jménem a heslem, protože někteří uživatelé tohle přihlašování přes třetí stranu nemají rádi.

Spring na to má dvě příručky – Spring Security and Angular (https://spring.io/guides/tutorials/spring-security-and-angular-js/) popisuje právě tu SPA, kde je každý REST požadavek autentizován JWT. Spring Boot and OAuth2 (https://spring.io/guides/tutorials/spring-boot-oauth2/) pak popisuje tu implementaci přihlášní pomocí Facebooku a GitHubu.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 27. 04. 2019, 13:40:37
A jakým způsobem bych řešil komunikaci té aplikace pomocí jenom https? Potřebuji to řešit jako celou aplikaci, ne jenom na straně springu.
Každopádně jsme zapomněl zmínit, že neumím react ani angular, takže bych to dělal v core javascriptu + jquery. Ale to by mělo jít také v pohodě, ne?
Takže tedy navrhujete implementovat ze zabezpečení aplikace:
- Ouath2
- JWT
- šifrování hesel
- nějaké obecné zabezpečení REST api
- asi by to chtělo nějakou ochranu proti těm běžným útokům ne? SQLinjection například? Nevím, zda spring to nějak defaultně nekryje, ale pokud ne, tak takové věci by tam asi měly také být.
- role. Pracoval jsem s nimi v celé springové aplikaci, přes rest nevím, jak to funguje a jestli to vůbec nějak jde...

Co jsem koukal, tak kdyby to nebylo přes rest, ale všechno ve springu psané, tak by se to https dalo přímo nastavit na straně springu...

Co si o tom všem myslíte? :)

Děkuji
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 27. 04. 2019, 14:03:51
Našel jsem k https tohle
https://www.baeldung.com/spring-boot-https-self-signed-certificate

To by šlo použít s rest api dohromady?
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 27. 04. 2019, 14:53:57
Použít jen HTTPS (a z HTTP udělat jen přesměrování na HTTPS) je jen otázka konfigurace webového serveru. Autentizaci přihlášením klientským certifikátem přes HTTPS bych nedělal, podpora v prohlížečích je špatná. Ne že by to neodporovaly, ale UX je otřesné. Například Chrome vyžaduje od uživatele každých pár minut PIN k čipové kartě s uloženým certifikátem, pokud se používá TLS 1.3, protože dohodnutí nových parametrů TLS dělají opravdu důkladně až k té nové žádosti o PIN.

Pokud použijete jen jQuery, musíte si napsat sám spoustu věcí, které vám jinak poskytují ty frameworky. Angular je už dost velký framework, myslím, že by stačilo i něco lehčího – třeba Vue.js (https://vuejs.org/). Myslím, že se ho člověk naučí docela rychle a postará se za vás o ty dvě nejnudnější věci, které musíte pořád řešit v čistém JavaScriptu – propojení dat v JavaScriptovém objektu na HTML prvky (vstupní políčka formulářů a výstup) a spouštění akcí.

Pro autentizaci volání RESTových služeb jsem navrhoval použít protokol OAuth2, který k RESTovým požadavkům přidává JWT –JSON Web Token. V něm jsou zakódované údaje, které předal autentizační server, jsou jím podepsané a obvykle obsahují časovou značku. Autentizační server tedy vystaví JSON, ve kterém je uvedená identifikace uživatele (nějaké ID, login, e-mail apod.), může tam přidat další údaje jako třeba role uživatele a nastaví platnost tokenu třeba na 15 minut a celé to podepíše. REST server pak ověří podpis a časovou platnost toho tokenu a vytáhne si z něj potřebné údaje (např. ten login).

Hesla se na serveru nešifrují ale hashují, tj. z hashe nelze zpět získat původní heslo. Existují speciální hashovací funkce určené pro hesla, kterým tedy já osobně moc nevěřím, protože nejsou kryptograficky prověřené. Takže bych raději použil standardní SHA-256. Důležité je to, že se nehashuje samotné heslo, ale kombinace heslo+sůl+pepř. Sůl je nějaký náhodný text unikátní pro každé heslo a je uložený spolu s heslem. Pepř je také náhodný text, který ale vůbec není uložený v databázi, je někde v konfiguraci aplikace. Kdyby útočník získal databázi, nebude znát pepř a nemůže tedy zkoušet hesla hádat. Kdyby získal databázi i pepř, může zkoušet hesla hádat – zkusí nějaké heslo, k němu zná pepř i sůl, vypočítá hash a porovná ho s tím v databázi. Díky soli ale musí hádat každé heslo zvlášť. Když se nepoužije sůl ani pepř, může útočník použít tzv. duhové tabulky – tabulky, kde je ke spoustě hesel už vypočítaný hash. Pak mu stačí projít databázi a všechny uložené hashe hledat v těch duhových tabulkách. U jednoduchých hesel uspěje a získá tak hesla konkrétních uživatelů. Pokud byste chtěl o bezpečném ukládání hesel vědět víc, hodně o tom píše a přednáší Michal Špaček (https://www.michalspacek.cz/).

Co se týče SQL injection, takovou chybu musíte spíš pracně vyrobit – sám, nebo použitím nevhodného nástroje. SQL injection vzniká tak, že v programu skládáte ručně do textového řetězce SQL příkaz a jeho parametry. Třeba "SELECT * FROM table WHERE id = " + request.getId(). Když použijete JPA nebo Spring JDBCTemplate a parametry budete do SQL dotazů předávat pomocí mapování, SQL injection nemůže nastat (samozřejmě pokud není nějaká chyba v použitých knihovnách a nedělají to skládání řetězců interně v té knihovně).

Pro uživatelské role máte nejjednodušší použít Spring Security – poskytnete implementaci, která pro zadaného uživatele vrátí seznam jeho rolí, a pak už jenom stačí každou metodu REST controlleru označit anotací, ve které uvedete seznam rolí, které tu metodu smějí volat.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 28. 04. 2019, 12:39:47
Použít jen HTTPS (a z HTTP udělat jen přesměrování na HTTPS) je jen otázka konfigurace webového serveru. Autentizaci přihlášením klientským certifikátem přes HTTPS bych nedělal, podpora v prohlížečích je špatná. Ne že by to neodporovaly, ale UX je otřesné. Například Chrome vyžaduje od uživatele každých pár minut PIN k čipové kartě s uloženým certifikátem, pokud se používá TLS 1.3, protože dohodnutí nových parametrů TLS dělají opravdu důkladně až k té nové žádosti o PIN.

Pokud použijete jen jQuery, musíte si napsat sám spoustu věcí, které vám jinak poskytují ty frameworky. Angular je už dost velký framework, myslím, že by stačilo i něco lehčího – třeba Vue.js (https://vuejs.org/). Myslím, že se ho člověk naučí docela rychle a postará se za vás o ty dvě nejnudnější věci, které musíte pořád řešit v čistém JavaScriptu – propojení dat v JavaScriptovém objektu na HTML prvky (vstupní políčka formulářů a výstup) a spouštění akcí.

Pro autentizaci volání RESTových služeb jsem navrhoval použít protokol OAuth2, který k RESTovým požadavkům přidává JWT –JSON Web Token. V něm jsou zakódované údaje, které předal autentizační server, jsou jím podepsané a obvykle obsahují časovou značku. Autentizační server tedy vystaví JSON, ve kterém je uvedená identifikace uživatele (nějaké ID, login, e-mail apod.), může tam přidat další údaje jako třeba role uživatele a nastaví platnost tokenu třeba na 15 minut a celé to podepíše. REST server pak ověří podpis a časovou platnost toho tokenu a vytáhne si z něj potřebné údaje (např. ten login).

Hesla se na serveru nešifrují ale hashují, tj. z hashe nelze zpět získat původní heslo. Existují speciální hashovací funkce určené pro hesla, kterým tedy já osobně moc nevěřím, protože nejsou kryptograficky prověřené. Takže bych raději použil standardní SHA-256. Důležité je to, že se nehashuje samotné heslo, ale kombinace heslo+sůl+pepř. Sůl je nějaký náhodný text unikátní pro každé heslo a je uložený spolu s heslem. Pepř je také náhodný text, který ale vůbec není uložený v databázi, je někde v konfiguraci aplikace. Kdyby útočník získal databázi, nebude znát pepř a nemůže tedy zkoušet hesla hádat. Kdyby získal databázi i pepř, může zkoušet hesla hádat – zkusí nějaké heslo, k němu zná pepř i sůl, vypočítá hash a porovná ho s tím v databázi. Díky soli ale musí hádat každé heslo zvlášť. Když se nepoužije sůl ani pepř, může útočník použít tzv. duhové tabulky – tabulky, kde je ke spoustě hesel už vypočítaný hash. Pak mu stačí projít databázi a všechny uložené hashe hledat v těch duhových tabulkách. U jednoduchých hesel uspěje a získá tak hesla konkrétních uživatelů. Pokud byste chtěl o bezpečném ukládání hesel vědět víc, hodně o tom píše a přednáší Michal Špaček (https://www.michalspacek.cz/).

Co se týče SQL injection, takovou chybu musíte spíš pracně vyrobit – sám, nebo použitím nevhodného nástroje. SQL injection vzniká tak, že v programu skládáte ručně do textového řetězce SQL příkaz a jeho parametry. Třeba "SELECT * FROM table WHERE id = " + request.getId(). Když použijete JPA nebo Spring JDBCTemplate a parametry budete do SQL dotazů předávat pomocí mapování, SQL injection nemůže nastat (samozřejmě pokud není nějaká chyba v použitých knihovnách a nedělají to skládání řetězců interně v té knihovně).

Pro uživatelské role máte nejjednodušší použít Spring Security – poskytnete implementaci, která pro zadaného uživatele vrátí seznam jeho rolí, a pak už jenom stačí každou metodu REST controlleru označit anotací, ve které uvedete seznam rolí, které tu metodu smějí volat.

Děkuji.
Jednu věc nechápu. Bavíme se o autentizaci přes OAuth2 a k tomu by měl být i možný způsob autentizaci i normální, že? Jakože klasická registrace na straně té aplikace.
Řekněme, že se uživatel přihlásí přes FB. Jak to ted bude reálně fungovat? Řekněme, že tam bude prostě úvodní stránka, kde se danému člověku budou vypisovat nové události ze všech společenstev, ve kterých je členem.
Čili by byl dotaz na DB - "neco... WHERE user.id = X;" - nicméně když se přihlásí přes FB, tak jak tohle zjistím, když toho člověka vlastně fyzicky v databázi nemám, ne? Tak jak zjistím, do jakých společenstev se přidal, na jakých bude akcích atd, když ho fyzicky v databazi mít nebudu?
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 28. 04. 2019, 12:43:59
Jo a ještě jedna věc...
U Rest Api jsem koukal, že je anotace @Secured(role) - jakým způsobem se přenáší ta role mezi springem a front endem? Uložená v jsonu nějak?
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 28. 04. 2019, 13:38:41
Autentizace říká, kdo je přihlášený uživatel. Způsobů autentizace můžete mít několik vedle sebe. Jeden asi bude jménem a heslem – uživatel zadá na formuláři jméno a heslo, vy ho podle jména v databázi vyhledáte a ověříte heslo. Když použijete přihlašování přes třetí stranu (např. Facebook), při registraci si opět uložíte údaje o uživateli do databáze, pak ho necháte přihlásit se přes Facebook a Facebook vám vrátí nějaký (pro Facebook) unikátní identifikátor toho uživatele. A ten vy si uložíte k tomu uživatelskému profilu do databáze. Když se příště přihlásí přes Facebooku, Facebook vám zase vrátí to samé ID a podle toho vy si v databázi najdete, který je to uživatel. Takže v databázi budete mít nejspíš nějakou tabulku s uživatelským profilem (třeba jeho jméno, příjmení a e-mail), vedle toho jinou tabulku se jménem a heslem a další tabulku s ID z Facebooku. A k jednomu profilu můžete mít uložený jak záznam v tabulce se jménem a heslem, tak záznam v tabulce Facebooku – uživatel si pak může vybrat, kterou variantou se přihlásí.

HTTP je ale bezstavový protokol, tedy normálně by uživatel musel zadávat své jméno a heslo (nebo se přihlašovat přes Facebook) s každým požadavkem, který se pošle na server. To samozřejmě nikdo dělat nebude – místo toho server uživatele ověří jednou a na základě toho předá klientovi nějakou informaci, kterou pak klient posílá s každým dalším požadavkem. A podle ní server pozná, že jde o toho přihlášeného klienta. Dříve se to dělalo tak, že server přidělil přihlášenému uživateli nějaké unikátní číslo (nazývané třeba session ID), a někam si poznamenal, že tohle session ID je uživatel třeba Franta Novák. Pak session ID poslal klientovi a ten ho přidával jako cookie do každého dalšího požadavku na server. Server si podle toho session ID z cookie dohledal příslušný záznam a z něj si přečetl, že s tímhle session ID je přihlášený uživatel Franta Novák. To má tu nevýhodu, že musí být na serveru to úložiště session ID, takže můžete mít jenom jeden server, nebo – když jich máte víc – potřebujete mezi nimi sdílet to úložiště session ID.

A tady do toho vstupuje ten OAuth2 protokol. Místo toho, aby si server poznamenával session ID, tak vytvoří elektronický dokument (ve formátu JSON), který říká „přihlášený uživatel je Franta Novák“, a případně k tomu doplní další údaje. A tenhle dokument elektronicky podepíše a pak ho i s tím podpisem předá klientovi. Klient pak ke každému požadavku nepřidává session ID, ale tenhle elektronicky podepsaný dokument, kterému se říká (autentizační) token (ve skutečnosti je velmi krátký, desítky znaků). Když ho dostane server, ověří ten podpis, a pokud sedí, ví, že může důvěřovat té informaci „přihlášený uživatel je Franta Novák“. Tím pádem si server nemusí pamatovat žádné session ID, ale i když budete mít 80 serverů po celém světě, pokud bude každý z nich umět ověřit ten elektronický podpis, dokáže bezpečně zjistit, že jde o toho správného uživatele.

Ve vašem případě je pro tu autentizaci REST požadavků OAuth2 trochu kanón na vrabce, ale je to průmyslový standard, se kterým umí zacházet spousta knihoven a frameworků. A Spring už má podporu v sobě, takže nemusíte nic implementovat, jenom to nakonfigurujete. V dokumentaci Springu Spring Security Reference (https://docs.spring.io/spring-security/site/docs/5.2.0.BUILD-SNAPSHOT/reference/htmlsingle/#jc) jsou ty varianty použití OAuth2 popsané.

Druhá věc je, že OAuth2 se používá i přitom přihlašování třeba přes Facebook, ale to s tou autentizace REST požadavků nesouvisí. Vlastně byste tam měl OAuth2 použité na dvou nesouvisejících místech – pro přihlášení přes Facebook a pro autentizaci REST požadavků.

Aby vám fungovala anotace @Secured(role), musíte implementovat rozhraní UserDetailsService, kde je metoda, která vrací uživatele a jeho role. Ve vašem případě je nejjednodušší podle předaného identifikátoru si uživatele dohledat v databázi a z ní načíst i odpovídající role.

S OAuth2 by se to dalo udělat i tak, že se ty role načtou při přihlášení uživatele a přidají se do toho autentizačního tokenu, který se pak posílá s každým požadavkem. Díky tomu podpisu pak server ví, že tomu seznamu rolí může důvěřovat. To se ale používá spíš v případech, kdy máte oddělený server, který dělá autentizaci, a server, který poskytuje vlastní služby. Ten server pak nemusí vědět nic o uživatelích, prostě se jenom řídí tím, co je v tom tokenu.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 28. 04. 2019, 14:38:41
Mockrát Vám děkuji. Ta Vaše vysvětlení jsou pro mě (jako člověka, co s tím nikdy nepracoval) velmi pochopitelná. Čili navrhujete: Aby REST api bylo zabezpečené přes Oauth2 - tím způsobem, jak jste popisoval. Čili na serveru se vytvoří nějaký elektronický dokument podepsaný, který pošle na klienta a ověřuje ho podle podpisu. A FB/Google přihlášení byste do toho nedoporučoval? Že jste psal, že se bude míchat Oauth2 na dvou nesouvislých místech? A pokud by se mi podařilo do té aplikace toto implementovat + to hashování hesla + ty role, tak by to dle Vás bylo bezpečnostně v pořádku? Samozřejmě ještě nevím, co s tím https potom...
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 29. 04. 2019, 09:32:21
Mockrát Vám děkuji. Ta Vaše vysvětlení jsou pro mě (jako člověka, co s tím nikdy nepracoval) velmi pochopitelná.
Děkuji. Pro mne je to důležitá informace, že to vysvětlování má smysl a že to je srozumitelné. Abych si tu jen tak nepsal něco, čemu z 90 % nebude rozumět :-)

Čili navrhujete: Aby REST api bylo zabezpečené přes Oauth2 - tím způsobem, jak jste popisoval. Čili na serveru se vytvoří nějaký elektronický dokument podepsaný, který pošle na klienta a ověřuje ho podle podpisu.
Ano. Ten dokument, který se používá v OAuth2 protokolu, se nazývá JWT – JSON Web Token. Jeho generování a ověřování nebudete implementovat, ve Springu už jsou knihovny, které to implementují. Vy to musíte jen nakonfigurovat (jaké klíče se mají použít apod.) a implementovat věci, na kterých to generování a ověřování závisí. Např. když se uživatel přihlásí jménem a heslem, Spring zavolá vaší službu, které předá to jméno a heslo, vy implementujete vyhledání uživatele v databázi, ověření hesla a zjištění dalších údajů o uživateli (třeba jeho plné jméno a role) a tyhle údaje vrátí vaše služba Springu, a ten už z toho ten JWT vyrobí.

A FB/Google přihlášení byste do toho nedoporučoval? Že jste psal, že se bude míchat Oauth2 na dvou nesouvislých místech?
Že se to bude míchat na dvou místech bylo myšleno tak, aby vás nemátlo, že se ten protokol může v té aplikaci použít dvěma způsoby, které spolu nijak nesouvisí. Je spoust aplikací, které používají OAuth2 pro zabezpečení svých REST služeb, a přihlášení přes FB  nebo Google neimplementují. A naopak je spousta aplikací, které implementují přihlášení přes FB nebo Google, ale jiným způsobem OAuth2 nepoužívají.

Já osobně bych doporučoval v takové aplikaci mít implementované přihlášení minimálně přes FB, Google, MojeID a asi i Twitter, protože zejména u aplikací, které používám jen občas, je otravné přihlašovat se jménem a heslem. A to používám správce hesel, takže pro mne je to přihlášení jednodušší, než pro většinu lidí, kteří si musí nějaké heslo vymyslet a pak si ho pamatovat. Ale to přihlášení přes systémy třetích stran je volitelná funkce, dá se doplnit kdykoli později – spíš je to další funkce, kterou můžete přidat, když se budete chtít naučit něco dalšího.

A pokud by se mi podařilo do té aplikace toto implementovat + to hashování hesla + ty role, tak by to dle Vás bylo bezpečnostně v pořádku? Samozřejmě ještě nevím, co s tím https potom...
Z hlediska autentizace by to mělo být v pořádku, protokoly, o kterých se bavíme, jsou prověřené, implementace použitá ve Springu pokud vím nemá žádné známé bezpečnostní problémy. Jinak je ale potřeba bezpečnost řešit u každé části aplikace, nedá se říct, že by aplikace použitím nějaké technologie byla bezpečná. Vždy musíte počítat např. s tím, že uživatel v prohlížeči sice může zadat např. jen číslo, ale schopnější uživatel si umí z prohlížeče ten JWT vytáhnout a zavolá tu vaší RESTovou službu jinak, a místo čísla tam dá text nebo ho nevyplní vůbec. Aplikace v takovém případě má vypsat chybu ale hlavně nesmí udělat žádnou operaci, na kterou uživatel nemá oprávnění.

Aplikace ve Springu se myslím většinou nevystavují přímo do internetu – obvykle tam bývá předřazený proxy server (třeba Nginx). Na tom předřazeném serveru se nakonfiguruje HTTPS (a přesměrování z HTTP na HTTPS), ten proxy server pak už může komunikovat se Springovou aplikací nešifrovaným HTTP – běží buď na stejném serveru nebo ve stejné síti. A i kdyby ta Springová aplikace měla (sama) běžet přes HTTPS, je to jen otázka konfigurace, té aplikace se to nijak nedotkne. Ve frontendové části aplikace se HTTPS vyřeší ještě snadněji, tam jde jenom o to v URL pro volání RESTových služeb použít protokol https a ne http. A samozřejmě je potřeba i tu frontendovou aplikaci servírovat ze serveru přes HTTPS – u malé aplikace to může dělat ten samý server, který dělá proxy server té backendové Springové aplikaci. Tj. pak máte třeba Nginx server, na něm je nakonfigurované HTTPS a s tím serverem komunikuje webový prohlížeč. Ten Nginx jednak poskytuje (statické) soubory frontendové aplikace, a jednak určité URL (třeba https://example.com/api/*) přeposílá na tu backendovou aplikaci ve Springu.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 10. 05. 2019, 12:12:24
Mockrát Vám děkuji. Ta Vaše vysvětlení jsou pro mě (jako člověka, co s tím nikdy nepracoval) velmi pochopitelná.
Děkuji. Pro mne je to důležitá informace, že to vysvětlování má smysl a že to je srozumitelné. Abych si tu jen tak nepsal něco, čemu z 90 % nebude rozumět :-)

Čili navrhujete: Aby REST api bylo zabezpečené přes Oauth2 - tím způsobem, jak jste popisoval. Čili na serveru se vytvoří nějaký elektronický dokument podepsaný, který pošle na klienta a ověřuje ho podle podpisu.
Ano. Ten dokument, který se používá v OAuth2 protokolu, se nazývá JWT – JSON Web Token. Jeho generování a ověřování nebudete implementovat, ve Springu už jsou knihovny, které to implementují. Vy to musíte jen nakonfigurovat (jaké klíče se mají použít apod.) a implementovat věci, na kterých to generování a ověřování závisí. Např. když se uživatel přihlásí jménem a heslem, Spring zavolá vaší službu, které předá to jméno a heslo, vy implementujete vyhledání uživatele v databázi, ověření hesla a zjištění dalších údajů o uživateli (třeba jeho plné jméno a role) a tyhle údaje vrátí vaše služba Springu, a ten už z toho ten JWT vyrobí.

A FB/Google přihlášení byste do toho nedoporučoval? Že jste psal, že se bude míchat Oauth2 na dvou nesouvislých místech?
Že se to bude míchat na dvou místech bylo myšleno tak, aby vás nemátlo, že se ten protokol může v té aplikaci použít dvěma způsoby, které spolu nijak nesouvisí. Je spoust aplikací, které používají OAuth2 pro zabezpečení svých REST služeb, a přihlášení přes FB  nebo Google neimplementují. A naopak je spousta aplikací, které implementují přihlášení přes FB nebo Google, ale jiným způsobem OAuth2 nepoužívají.

Já osobně bych doporučoval v takové aplikaci mít implementované přihlášení minimálně přes FB, Google, MojeID a asi i Twitter, protože zejména u aplikací, které používám jen občas, je otravné přihlašovat se jménem a heslem. A to používám správce hesel, takže pro mne je to přihlášení jednodušší, než pro většinu lidí, kteří si musí nějaké heslo vymyslet a pak si ho pamatovat. Ale to přihlášení přes systémy třetích stran je volitelná funkce, dá se doplnit kdykoli později – spíš je to další funkce, kterou můžete přidat, když se budete chtít naučit něco dalšího.

A pokud by se mi podařilo do té aplikace toto implementovat + to hashování hesla + ty role, tak by to dle Vás bylo bezpečnostně v pořádku? Samozřejmě ještě nevím, co s tím https potom...
Z hlediska autentizace by to mělo být v pořádku, protokoly, o kterých se bavíme, jsou prověřené, implementace použitá ve Springu pokud vím nemá žádné známé bezpečnostní problémy. Jinak je ale potřeba bezpečnost řešit u každé části aplikace, nedá se říct, že by aplikace použitím nějaké technologie byla bezpečná. Vždy musíte počítat např. s tím, že uživatel v prohlížeči sice může zadat např. jen číslo, ale schopnější uživatel si umí z prohlížeče ten JWT vytáhnout a zavolá tu vaší RESTovou službu jinak, a místo čísla tam dá text nebo ho nevyplní vůbec. Aplikace v takovém případě má vypsat chybu ale hlavně nesmí udělat žádnou operaci, na kterou uživatel nemá oprávnění.

Aplikace ve Springu se myslím většinou nevystavují přímo do internetu – obvykle tam bývá předřazený proxy server (třeba Nginx). Na tom předřazeném serveru se nakonfiguruje HTTPS (a přesměrování z HTTP na HTTPS), ten proxy server pak už může komunikovat se Springovou aplikací nešifrovaným HTTP – běží buď na stejném serveru nebo ve stejné síti. A i kdyby ta Springová aplikace měla (sama) běžet přes HTTPS, je to jen otázka konfigurace, té aplikace se to nijak nedotkne. Ve frontendové části aplikace se HTTPS vyřeší ještě snadněji, tam jde jenom o to v URL pro volání RESTových služeb použít protokol https a ne http. A samozřejmě je potřeba i tu frontendovou aplikaci servírovat ze serveru přes HTTPS – u malé aplikace to může dělat ten samý server, který dělá proxy server té backendové Springové aplikaci. Tj. pak máte třeba Nginx server, na něm je nakonfigurované HTTPS a s tím serverem komunikuje webový prohlížeč. Ten Nginx jednak poskytuje (statické) soubory frontendové aplikace, a jednak určité URL (třeba https://example.com/api/*) přeposílá na tu backendovou aplikaci ve Springu.

Zdravím,
a jak to ještě funguje s CSRF? Řekněme, že bych použil Oauth2 k zabezpečení těch REST služeb. CSRF hrozí? Případně mu předpokládám je vhodné nějakým způsobem zamezit?

Děkuji
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 10. 05. 2019, 19:53:47
a jak to ještě funguje s CSRF? Řekněme, že bych použil Oauth2 k zabezpečení těch REST služeb. CSRF hrozí? Případně mu předpokládám je vhodné nějakým způsobem zamezit?
CSRF spočívá v tom, že v okamžiku, kdy je uživatel přihlášen do aplikace, přinutíte prohlížeč, aby poslal platný požadavek včetně autentizačních údajů. To funguje například tehdy, když je přihlášený uživatel identifikován pomocí cookie – prohlížeč ji přibalí automaticky k požadavku, i když byl požadavek odeslán z jiné webové stránky. Při použití OAuth2 se ale autentizační token obvykle posílá v hlavičce Authorization a o jeho přiložení se musí postarat ten kód, který tu RESTovou službu volá – tj. nedělá to prohlížeč automaticky. Tedy případný útočník by musel autentizační token také připojit k požadavku ručně – ale to by jej nejprve musel získat. Pokud bude uložený např. jen v JavaScriptové aplikaci na klientovi, tak token získat nemůže (pokud v té aplikaci není speciální kód, který by to umožnil). Případně může být ten token uložen v Session Storage nebo Local Storage – ty jsou vázané na doménu, takže útočící skript z jiné domény se k nim nedostane. Nicméně pokud by pod jednou doménou běželo několik aplikací, ty už by si mohly navzájem číst Session Storage nebo Local Storage. Ale pokud poběží víc aplikací pod jednou doménou, těch způsobů, jak se navzájem ovlivnit, je mnoho – takže bych buď počítal s tím, že na dané doméně bude aplikace samotná, a nebo tam budou jen důvěryhodné aplikace.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 11. 05. 2019, 00:02:24
Děkuji.
Čili za předpokladu, že budu používat Oauth2 pro ty rest api, budu mít aplikaci, kdy bude jeden server a jakože "jeden" front end, tak k CSRF nemůže dojít, pokud ten token bude prostě uložený někde v JS kodu na klientovi. Je to takto správně? Já jsem
A existují nějaké útoky přímo na ten Oauth2, na který bych si měl dát pozor?
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 11. 05. 2019, 08:59:53
Ano, pokud ten token bude uložen v JS aplikaci na frontendu, z pohledu CSRF je to bezpečné – útočník se k tokenu nemůže dostat a prohlížeč ho neposílá automaticky, tj. požadavek s validním tokenem nemůže odejít jinak, než přímo z vaší aplikace.

Pokud se OAuth2 implementuje podle aktuálních doporučení, žádný známý útok mne nenapadá. Jedině to, že u Single Page Aplikací (SPA) se dříve doporučovalo u autentizace přes OAuth2 implicit flow, dnes už se doporučuje provést i v tomhle případě standardní získání tokenu. Celý proces přihlášení přes OAuth2 je odbře popsán teřba v OAuth 2 Simplified (https://aaronparecki.com/oauth-2-simplified/) a jsou tam i odkazy na aktuální doporučení.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 02. 07. 2019, 11:00:12
Ano, pokud ten token bude uložen v JS aplikaci na frontendu, z pohledu CSRF je to bezpečné – útočník se k tokenu nemůže dostat a prohlížeč ho neposílá automaticky, tj. požadavek s validním tokenem nemůže odejít jinak, než přímo z vaší aplikace.

Pokud se OAuth2 implementuje podle aktuálních doporučení, žádný známý útok mne nenapadá. Jedině to, že u Single Page Aplikací (SPA) se dříve doporučovalo u autentizace přes OAuth2 implicit flow, dnes už se doporučuje provést i v tomhle případě standardní získání tokenu. Celý proces přihlášení přes OAuth2 je odbře popsán teřba v OAuth 2 Simplified (https://aaronparecki.com/oauth-2-simplified/) a jsou tam i odkazy na aktuální doporučení.

Zdravím,
tak se do toho pomalu pouštím, včera jsem začal studoval Oauth2 a začal trošku i to programovat. Nicméně motá mi hlavu toto...
1) Dočetl jsem se, že má být client id a client secret. A to má být oboje nějak zašifrovaný. Proč?
2) Povedlo se mi udělat, že jsem si vygeneroval certifikát a podepsal na autorizačním serveru privátním klíčem, public klíčem jsem to rozšifroval - ALE... Mám používat cliend id s client secret nebo to podepisování? A nebo oboje? Případně proč?
3) Chtěl bych ještě docílit toho, že se vypočte u těch JWT, zda ten JWT nebyl nějak změněn. Dá se toho nějak docílit?

Ta bakalářka jinak bude o něčem jiném, tamto téma mi neprošlo (neschválilo mi to vedení), takže se to muselo hodit spíše do bezpečnosti.
Případně, mohl bych se Vám takhle někdy zase ozvat, kdybych v něčem byl zaseknutý?

Mockrát děkuji
Mohl bych Vás
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 02. 07. 2019, 13:30:53
Client-id je veřejný údaj, ten není potřeba šifrovat. Client secret se používá v případě, kdy se autentizuje serverová aplikace, do které můžete ten klíč client secret schovat. Pokud se autentizuje webová aplikace běžící v prohlížeči, client secret se nepoužívá – bezpečnost je založená na tom, že autentizační server po dokončení autentizace přesměruje prohlížeč na adresu, která je svázaná s daným klientem. Tj. i kdyby přihlášení zahájil útočník, skončí to tak, že se uživatel přihlásí do té správné (ne útočníkovi) aplikace.

Pro podpis JWT se pak mohou použít dvě různé metody – buď  se používá sdílený klíč, nebo klasický elektronický podpis s veřejným a privátním klíčem. Ten sdílený klíč se používá v případě, kdy si aplikace navzájem důvěřují a vše je na serveru, takže se sdílený klíč k nikomu cizímu nedostane. Aplikace, která JWT token jenom ověřuje, totiž musí mít ten samý klíč, který se používá pro vytvoření podpisu – škodlivá aplikace by tudíž mohla sama vytvořit falešný JWT, který by ale byl podepsán tím správným klíčem, a třetí aplikace by mu důvěřovala.

Druhá možnost je použití veřejného a privátního klíče. To používají třeba veřejné služby – když se přihlašujete prostřednictvím Google nebo Twitteru, dají vám jenom veřejný klíč. Nemohou použít přístup se sdíleným klíčem, protože pak by tím jejich klíčem mohl kdokoli podepsat JWT, který by pak vypadal jako skutečný JWT od Googlu nebo Twitteru. Implementačně je ten způsob s dvojicí klíčů trochu složitější, ale většinou používáte nějakou knihovnu, kde už je to podepisování zapouzdřené a vy to nemusíte řešit. Pokud tedy klienta nemáte pod kontrolou (buď je to webová aplikace v prohlížeči, a nebo aplikace třetích stran), používá se tahle druhá metoda s veřejným i privátním klíčem. My to například budeme používat i v jednom spolku, kde se bude autentizovat víc různých aplikací. Sice jsou všechny ty aplikace „naše“ a mohli bychom jim věřit, ale očekáváme, že i ty „naše“ aplikace budou různě důvěryhodné – takže rovnou použijeme tu variantu s veřejným a privátním klíčem, a ten privátní klíč bude znát jenom aplikace provádějící autentizaci.

Kontrola toho, zda JWT nebylo změněno, by se měla provádět vždy, když se JWT použije (budete z něj číst nějaká data). K tomu právě slouží ten podpis. V knihovnách to obvykle bývá nazváno jako validace a ověří se právě to, že podpis sedí s daty, tj.  po podepsání nedošlo ke změně dat. K validaci je právě potřeba znát buď ten sdílený klíč nebo veřejný klíč, podle toho, co se používá.


Mám na tohle diskusní téma zapnuté e-mailové notifikace, takže když sem vložíte příspěvek, dozvím se to, a pokusím se poradit, pokud budu vědět.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthon 02. 07. 2019, 19:21:34
Přemýšlím, jakým způsobem to udělat na front endu s oauthem2.
1.) Potřeboval bych login a po úspěšném loginu jako být na jiné stránce (index.html) třeba. Čili nápad by byl, že když dostane klient ten access_token, tak se přes JS udělá redirect na ten index.html. Ale řeknemě, že ten login bude první stránka, která se má objevit - třeba mojestranka.cz/login.html - Jak ale zamezím tomu, že si tam uživatel třeba napíše mojestranka.cz/index.html a dostane se na tu indexovou stránku i bez toho tokenu?

2.) Řekněme, že ten token je elektronicky podepsanej. Na klientskou část aplikace bych nahrál public klíč. Jak to potom na té front endové části přeložím do nějaké čitelné formy pro mě?

Děkuji
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 03. 07. 2019, 08:20:29
Každá stránka by si měla kontrolovat, zda je token k dispozici – a pokud není, přesměrovat uživatele na přihlašovací stránku.

JWT je jen JSON zakódovaný v BASE64 (resp. jsou to tři objekty, každý se zakóduje do BASE64 a vše se pak spojí tečkou do jednoho řetězce). Takže získat z toho ty údaje (pokud byste neprováděl validaci) jde i ručně. Lepší je ale použít hotovou knihovnu, např. na jwt.io (https://jwt.io/#libraries-io) je docela dobrý přehled knihoven pro různé jazyky.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 03. 07. 2019, 21:44:52
Narazil jsem dneska na problém při AJAxu z front endu. Nemohu dostat ten access token, když mám server na localhostu evidentně... hlási mi to CORS...
Nakonec jsem to částečně vyřešil tímto requestem pomocí jQuery.

Kód: [Vybrat]
$.ajax({
        url: 'http://localhost:8080/oauth/token',
        "async": true,
        crossDomain: true,
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json; charset=UTF-8',
        headers: {"Authorization": "Basic bXktY2xpZW50Om15LXNlY3JldA==", "Content-Type": "application/x-www-form-urlencoded"},
        data: {
            "password": "George",
            "username": "pleb@seznam.cz",
            "grant_type": "password"
          },

        complete: function(result) {
            alert(result + " COMPLETE ");
        },

        success: function(result) {
            alert(result + " OK!");
        },

        error: function(result) {
            alert(result + " CHYBA");
        },
    });
    return true;
}

Nicméně aby to fungovalo, tak jsem musel ještě udělat tuto třídu na straně serveru

Kód: [Vybrat]
@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class CorsConfig implements Filter {

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        HttpServletRequest request = (HttpServletRequest) req;

        response.setHeader("Access-Control-Allow-Origin", "*");
        response.setHeader("Access-Control-Alow-Methods", "POST, GET, OPTIONS, DELETE, PUT");
        response.setHeader("Access-Control-Max-Age","3600");
        response.setHeader("Access-Control-Allow-Headers", "x-requested-with, authorization, content-type");

        if("OPTIONS".equalsIgnoreCase(request.getMethod())){
            response.setStatus(HttpServletResponse.SC_OK);
        } else {
            chain.doFilter(req, res);
        }
    }


    @Override
    public void destroy() {

    }
}


Což je zřejmě nebezpečné takto to ponechat, že? Napadlo by Vás nějaké řešení, jak tohle vyřešit? Abych se dostal k tomu oauth2 tokenu bez toho, abych musel dělat ten filtr?
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 03. 07. 2019, 21:58:54
Pokud běží REST API na jiném hostname, než webová aplikace (typicky to tak je), musí ten REST server posílat Access-Control-* hlavičky, aby prohlížeč komunikaci akceptoval. Je to ochrana před tím, aby webová stránka nemohla volat REST služby serveru, který s tím nepočítá – mohla by tak na ten server útočit.

Akorát ve Springu to nemusíte řešit ručně, má už pro to podporu: Enabling Cross Origin Requests for a RESTful Web Service (https://spring.io/guides/gs/rest-service-cors/).
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 04. 07. 2019, 15:30:17
Takže to mé řešení je v pohodě, že? :-)

Nedaří se mi zjistit, jak správně podepsat to JWT.

Na tom autorizačním serveru se mi to podepíše v pohodě (zkoušel jsem to přes tu stránku jwt.io a podpis se ověří při použití public key), ale v aplikaci nevím, jak udělat to ověření na tom resource serveru...
Zkoušel jsem i auth0, tam je problém, že nevím, jak:

1) Vložím vytvořený token tím auth0 do té odpovědi...
2) Při ověření na resource serveru bych potřeboval přístup k tomu tokenu ve stringové formě, abych to mohl přes tu jejich funkci ověřit... na to jsem také zatím nepřišel, jak na resource serveru můžu dostat přístup k access_tokenu, který tam zrovna přišel...

Ten podpis a ověření v tom mém kodu probíhá u accessTokenConverteru.

Kód: [Vybrat]
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    private static final String GRANT_TYPE_PASSWORD = "password";
    private static final String AUTHORIZATION_CODE = "authorization_code";
    private static final String REFRESH_TOKEN = "refresh_token";
    private static final String SCOPE_READ = "read";
    private static final String SCOPE_WRITE = "write";
    private static final String TRUST = "trust";
    private static final int VALID_FOREVER = -1;

    @Autowired
    private AuthenticationManager authManager;
   
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients
                .inMemory()
                .withClient(Const.CLIENT_ID)
                .secret(Const.CLIENT_SECRET)
                .authorizedGrantTypes(GRANT_TYPE_PASSWORD, AUTHORIZATION_CODE, REFRESH_TOKEN)
                .scopes(SCOPE_READ, SCOPE_WRITE, TRUST)
                .accessTokenValiditySeconds(500)
                .refreshTokenValiditySeconds(VALID_FOREVER);
    }
   
    @Bean
    public TokenStore tokenStore() {
        return new JwtTokenStore(accessTokenConverter());
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        final JwtAccessTokenConverter converter = new JwtAccessTokenConverter(){
            @Override
            public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
                if(authentication.getOAuth2Request().getGrantType().equalsIgnoreCase("password")) {
                    final Map<String, Object> additionalInfo = new HashMap<String, Object>();
                    additionalInfo.put("organization", "NEJAKA INFORMACE");
                    ((DefaultOAuth2AccessToken) accessToken)
                            .setAdditionalInformation(additionalInfo);

                }
                accessToken = super.enhance(accessToken, authentication);
                ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(new HashMap<>());
                return accessToken;
            }
        };

       KeyStoreKeyFactory keyStoreKeyFactory =
                new KeyStoreKeyFactory(new ClassPathResource("test.jks"), "password".toCharArray());
        converter.setKeyPair(keyStoreKeyFactory.getKeyPair("test"));

        return converter;
    }
   
   
   
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(accessTokenConverter()));

        endpoints.tokenStore(tokenStore())
                .tokenEnhancer(accessTokenConverter())
                .accessTokenConverter(accessTokenConverter())
                .authenticationManager(authManager);
    }
}

Kód: [Vybrat]
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {

    private static final String RESOURCE_ID = "resource_id";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID).stateless(false);
        resources.tokenStore(tokenStoree());
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.
                anonymous().disable()
                .authorizeRequests()
                .antMatchers("/aadmin/**").authenticated()
                .and().exceptionHandling().accessDeniedHandler(new OAuth2AccessDeniedHandler());

        http
                .sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
    }

    @Bean
    public JwtAccessTokenConverter accessTokenConverterr() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        Resource resource = new ClassPathResource("public.txt");
        String publicKey = null;
        try {
            publicKey = IOUtils.toString(resource.getInputStream());
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
        converter.setVerifierKey(publicKey);

        return converter;
    }

    @Bean
    public DefaultTokenServices tokenServices(final TokenStore tokenStore) {
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenStore(tokenStoree());
        return tokenServices;
    }


    @Bean
    public TokenStore tokenStoree() {
        return new JwtTokenStore(accessTokenConverterr());
    }
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 05. 07. 2019, 17:10:56
A ještě jedna věc, prosím.

Přemýšlím, zda použít implicit flow nebo authorization_code. Ten produkt by měl být pro jednu společnost, která bude sdílet dokumenty, události, bude požadovat přečtení dokumentu atd ve zkratce... čili bych předpokládal, že by mělo být možné uchovat "secret" někde bezpečně (jinak než například v cookies nebo localStorage). Myslíte, že mám v mém případě použít ten authorization flow nebo implicit flow?

Mockrát děkuji
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 06. 07. 2019, 11:08:25
Používáte podporu pro resource server, která je součástí Spring Boot, takže JWT nebudete ověřovat ručně. O ověření se postará Spring Boot a z vašeho pohledu to bude fungovat stejně, jako jakýkoli jiný způsob přihlášení. Tzn. deklarujete, které části aplikace může používat anonymní uživatel, které přihlášený, případně jakou roli musí mít uživatel, aby mohl použít danou službu. Je dobré to ověřit tak, že vyzkoušíte přístup s platným tokenem, s expirovaným tokenem, s tokenem s nevalidním podpisem a bez tokenu. K aplikaci byste se měl dostat jenom s platným tokenem, v ostatních případech musí server vrátit nějakou chybu.

Implicit flow se už dnes nepoužívá. Byl navržený pro aplikace v prohlížeči, ale i tam už se dnes doporučuje používat authorization flow, akorát se v takovém případě nepoužívá client secret (protože u aplikace běžící kompletně v prohlížeči není kam ho schovat).
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 06. 07. 2019, 15:03:13
A jakým způsobem zavolám potom ten request, abych dostal ten token, když použiju authorization code bez secretu?
Když v postmanovi zkouším se secretem, že nastavím basic auth. a zadám client_id a secret a do body dám grant_type, username, password, tak to funguje bez problémů. Ale pokud na autorizačním serveru dám pryč ten secret akorát, v POSTMANovi nechám Basic Auth., ale nezadám secret, tak mi to vrátí 401.

Ještě jsem četl nějaké články, kam uložit access_token a refresh_token a dočetl jsem se, že localStorage i sessionStorage nejsou bezpečné. Kam na tom front endu je tedy dobré to bezpečně uložit dle Vás? Nebo pokud bych nějakými způsoby ošetřil XSS útok na localStorage (whitelist atd), myslíte, že by to bylo ok? :-)

Děkuji
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 06. 07. 2019, 20:03:51
Spring musí být nakonfigurován, aby povolil ten přístup bez client secret – dá se k tomu něco najít např. zde: Spring Security OAuth 2.0 - client secret always required for authorization code grant (https://stackoverflow.com/questions/35785628/spring-security-oauth-2-0-client-secret-always-required-for-authorization-code?rq=1).

Podle mne je local storage nebo session storage bezpečné úložiště pro ty tokeny – dostanou se k němu jenom skripty z příslušné domény. Pokud jde o SPA aplikaci, můžete ten token uložit i přímo v aplikaci, ale pak dojde k odhlášení uživatele když obnoví stránku (F5).
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 09. 07. 2019, 22:52:22
Jakým bezpečným způsobem posílat access token na server s requestem?

Pokud udělám: https://localhost:8443/docs?access_token=12345 (a používám https) je to v pohodě? Nebo jakým jiným způsobem tu GET metodu poslat na server?

Respektive. Když dám v prohlížeči Sít (firefox), tak tu request na ten server vidím a vidím i ten access_token v tom URL samozřejmě...

Mockrát děkuji
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 10. 07. 2019, 09:50:06
Token pro autorizaci požadavků na resource server se obvykle posílá v hlavičce Authorization – použije se typ autentizace  „Bearer“ a pak je uvedený token. Tj. HTTP hlavička pak vypadá takhle:

Kód: [Vybrat]
Authorization: Bearer <token>

Resource server s podporou JWT by měl umět vyzvednout si JWT token z této hlavičky.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 16. 07. 2019, 12:15:32
Zdravím,
dneska jsem se dostal do úzkých s many-to-many mapováním s "extra column". Podařilo se mi to namapovat tak, aby se mi vytrvořily tabulky v databázi OK. Nicméně problém mám s tím ,že nevím, jakým způsobem uložit ten objekt do databáze...

Document
Kód: [Vybrat]
@JsonIgnore
    @OneToMany(mappedBy = "document")
    private List<UsersDocuments> documentsForUsers;

User
Kód: [Vybrat]
@OneToMany(mappedBy = "user", orphanRemoval = true, cascade= CascadeType.ALL)
private List<UsersDocuments> usersDocuments;

PK
Kód: [Vybrat]
@Embeddable
public class UserDocumentsId implements Serializable {

    @Column(name="user_id")
    private long user;

    @Column(name="document_id")
    private long document;

Kód: [Vybrat]
@Entity
@Table(name="users_documents")
public class UsersDocuments {

    @EmbeddedId
    private UserDocumentsId id;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("user")
    @JoinColumn(name = "user_id")
    private User user;

    @ManyToOne(fetch = FetchType.LAZY)
    @MapsId("document")
    @JoinColumn(name = "document_id")
    private Document document;

    @Column(name="approval")
    private boolean approval;

Ukládání - nefunkční.
document.getDocumentsForUsers().add(userDocuments); hází NULL exception.
Kód: [Vybrat]
Optional<User> user = userService.getUserByEmail(createdBy);
        Document document = new Document(title, desc);
        document.setUploadDatetime(new Date());
        document.setUser(user.get());

        List<User> users = userService.getUsersByRoles(roles);


        for(User userx : users){
            UsersDocuments userDocuments = new UsersDocuments();
            UserDocumentsId id = new UserDocumentsId();

            // Construct the Id with user and document
            id.setUser(userx.getId());
            id.setDocument(document.getId());

            userDocuments.setId(id);
            userDocuments.setApproval(true);

            document.getDocumentsForUsers().add(userDocuments);
        }

        documentService.saveDocument(document);

Mockrát děkuji
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 16. 07. 2019, 20:20:54
Vytváříte tam objekt Document a pravděpodobně nikde nenastavujete fieldu documentsForUsers nějakou hodnotu – v deklaraci to nemáte a nejspíš to není ani v konstruktoru. document.getDocumentsForUsers() pak vrací null a pokus o volání metody na null skončí NullPointerException.

Jinak s ORM vám asi nepomůžu, já mám k ORM vrozený odpor (podle mne je to nástroj, který dělá víc škody než užitku) a zatím se mu úspěšně vyhýbám… (Ne že bych nedělal i na projektech, kde se používá ORM, ale nemusím u nich ORM řešit.)
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 17. 07. 2019, 19:51:17
Ještě Vás poprosím další věc ohledně toho oauthu.

Dočetl jsem se, že se má uvádět:
Content-Type": "application/x-www-form-urlencoded
Je nutné tento content-type mít vždy tento, nebo jen při autentizaci/refresh_token atd?

Mám problém s tím, že mi nejdou posílat requesty na server, když ta data jsou v body. Spring mi to nebere:
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported]
Za předpokladu, že použiji:
application/json
Tak je vše v pohodě...
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 17. 07. 2019, 20:26:02
Kód: [Vybrat]
@PutMapping(value = "", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
    @Secured({("ROLE_USER"),("ROLE_SUPERIOR"), ("ROLE_ADMIN")})
    public void updateApproval(OAuth2Authentication auth, @RequestParam MultiValueMap<String, String> body){
        String email = auth.getName();
        long userId = userService.getUserByEmail(email).get().getId();

        String approvalString  = body.getFirst("approval");
        int approval = Integer.parseInt(approvalString);

        String doc_ids = body.getFirst("doc_id");
        long doc_id = Long.parseLong(doc_ids);
        documentService.updateSharing(userId, doc_id, approval);
    }

takhle jsem vyřešil ten problém, aby mi to bralo tenhle content-type a v AJAXu jsem neposlal JSON data... každopádně má otázka trvá... a zda je tento kod, co sem ted dávám v pořádku řešení.

Děkuji
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 05. 08. 2019, 15:42:06
Zdravím,

je nějaký doporučený způsob, jak se vypořádat s XSS na straně springu? To znamená provéct XSSstrip všech requestů? Jak pro GET tak POST? Podařilo se mi udělat pouze pro GET, ale já bych potřeboval, aby to šlo pro všechno... jak pro GET, POST, PUT...

Děkuji :)
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 12. 08. 2019, 10:32:37
Dočetl jsem se, že se má uvádět:
Content-Type": "application/x-www-form-urlencoded
Je nutné tento content-type mít vždy tento, nebo jen při autentizaci/refresh_token atd?

Mám problém s tím, že mi nejdou posílat requesty na server, když ta data jsou v body. Spring mi to nebere:
Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/x-www-form-urlencoded;charset=UTF-8' not supported]
Za předpokladu, že použiji:
application/json
Tak je vše v pohodě...
Content-Type určuje, v jakém formátu odesíláte data na server (a opačně v hlavičkách odpovědi říká, v jakém formátu je odpověď). Pro data posílaná v těle požadavku při OAuth je správný typ application/x-www-form-urlencoded – data se posílají, jako by to byl vyplněný HTML formulář. Spring by to v rámci autentizace měl zpracovat sám, pokud byste autentizaci implementoval sám, musí kontroler nakonfigurovat, aby tento typ dat přijímal (standardně Spring očekává data ve formátu JSON).

je nějaký doporučený způsob, jak se vypořádat s XSS na straně springu?
XSS byste měl řešit na straně view. Pokud uživatel na server odešle např. znak <, chce, aby se ten znak zobrazil – vy byste ho tedy měl normálně uložit do databáze. Při renderování obsahu ve view pak musíte zajistit, aby se speciální znaky escapovaly – např. < se musí vyrenderovat jako &lt; do zdrojového kódu HTML, protože ten znak má jinak v HTML speciální význam. Ale kdybyste chtěl ten samý text vyrenderovat třeba do PDF, nebudete řešit znak <, protože v PDF žádný speciální význam nemá.

Řešit to na straně vstupu je špatně, protože tím měníte data, která poslal uživatel – zobrazíte pak něco jiného, než poslal. Navíc pak očekáváte, že v databázi už máte všechna data vyčištěná a zobrazujete je bez escapování, což je dost „odvážné“. Navíc escapuje se podle použitého výstupního formátu, tj. jinak se escapuje pro HTML, jinak pro PDF, jinak pro čistý text – a třeba se jinak budou escapovat budoucí verze HTML. V databázi byste tedy měl mít uložen původní vstup od uživatele, protože nikdy nevíte, jak ho budete potřebovat escapovat v budoucnosti.
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Arthnon 13. 08. 2019, 17:38:39

je nějaký doporučený způsob, jak se vypořádat s XSS na straně springu?
XSS byste měl řešit na straně view. Pokud uživatel na server odešle např. znak <, chce, aby se ten znak zobrazil – vy byste ho tedy měl normálně uložit do databáze. Při renderování obsahu ve view pak musíte zajistit, aby se speciální znaky escapovaly – např. < se musí vyrenderovat jako &lt; do zdrojového kódu HTML, protože ten znak má jinak v HTML speciální význam. Ale kdybyste chtěl ten samý text vyrenderovat třeba do PDF, nebudete řešit znak <, protože v PDF žádný speciální význam nemá.

Řešit to na straně vstupu je špatně, protože tím měníte data, která poslal uživatel – zobrazíte pak něco jiného, než poslal. Navíc pak očekáváte, že v databázi už máte všechna data vyčištěná a zobrazujete je bez escapování, což je dost „odvážné“. Navíc escapuje se podle použitého výstupního formátu, tj. jinak se escapuje pro HTML, jinak pro PDF, jinak pro čistý text – a třeba se jinak budou escapovat budoucí verze HTML. V databázi byste tedy měl mít uložen původní vstup od uživatele, protože nikdy nevíte, jak ho budete potřebovat escapovat v budoucnosti.
[/quote]

Čili data, která přijdou na server bych neměl na vstupu nijak kontrolovat/odescapovávat a normálně je rovnou uložit do databáze? Čili na serveru nemusím dělat žádnou kontrolu vůči XSS útokům? Nebo to mám zkontrolovat (udělat escapování) těsně před tím, než pošlu data na view? Nebo poslat ta data přímo z DBa udělat escapování a kontrolu těch dat až na view při renderování dat?
Název: Re:Nápad na bakalářskou práci se Spring
Přispěvatel: Filip Jirsák 13. 08. 2019, 22:02:01
Čili data, která přijdou na server bych neměl na vstupu nijak kontrolovat/odescapovávat a normálně je rovnou uložit do databáze? Čili na serveru nemusím dělat žádnou kontrolu vůči XSS útokům? Nebo to mám zkontrolovat (udělat escapování) těsně před tím, než pošlu data na view? Nebo poslat ta data přímo z DBa udělat escapování a kontrolu těch dat až na view při renderování dat?
Na vstupu byste data měl kontrolovat – tj. pustit dál jenom taková data, která mají smysl, platné hodnoty. Třeba pokud někde má být věk v letech, musí to být nezáporné celé číslo, a je rozumné alespoň s varováním kontrolovat i nějakou horní hranici. Ale ne escapovat – pokud uživatel zadává např. obyčejný text, je posloupnost <script> legální posloupností (co když uživatel třeba bude posílat část svého kódu). Escapovat je nutné na výstupu – aby se zobrazilo zase <script>, co zadal uživatel, a ne aby se místo toho vložil do HTML skutečný skript.

Escapování by se mělo ideálně dělat až ve view při renderování dat. Rozumné knihovny pro view jsou dokonce navržené tak, že ve výchozím nastavení samy escapují a pokud escapovat nechcete, protože máte příslušná data ošetřená jinak, musíte to speciálně zadat. Pokud takovou funkci knihovna pro view nemá, musel byste escapovat před tím, než data pošlete do view. Ale tomu bych se snažil vyhnout, protože na to určitě někde zapomenete.