24. března 2008

Konkurenční přístup k datům - zamykací mechanismy, díl první

Každý asi ví, že konkurenční přístup k datům je nutné řešit, ať už na datové nebo aplikační úrovni. Mám ovšem tu zkušenost, že většina kolegů tento problém řeší až v době implementace případu užití, což si myslím, že už je trochu pozdě. Přístup k datům resp. zvolený zamykací mechanismus ovlivňuje návrh samotné aplikace (datový model nebo aplikaci samotnou) a proto by způsob přístupu k datům měl být vyjasněn již v době analýzy a zohledněn v návrhu aplikace.
Rád bych tedy v sérii několika článků zmínil základní způsoby řešení konkurenčního přístupu k datům - ať už na úrovni datové nebo aplikační.

Optimistické zamykání

Navzdory svému jménu vlastně o žádné zamykání nejde. Transakce přistupují k datům bez nějakého omezení, pouze při updatu se ověřuje, zda data nebyla v průběhu transakce změněna jinou transakcí od doby, kdy se data načetla. V případě kolize je nutné transakcí vrátit (roll-back).
Kontrola změny dat se může řešit pomocí:
  • evidence verze. Pro tuto variantu je nutné přidat nový speciální sloupec do tabulky pro evidenci verze. Při každé změně hodnoty se zvýší verze a pak je jednoduché zjistit, zda došlo ke změně nebo nikoliv.

  • evidence času poslední změny. Víceméně totožné jako předchozí varianta, ale místo verze se eviduje timestamp poslední změny.

  • porovnání nové a původní hodnoty. Velké výhoda tohoto přístupu je ta, že není nutné přidávat žádný sloupec, tedy vhodné pro systémy, kde nemůžeme provádět úpravy v datovém modelu.

Většina ORM nástrojů minimálně jeden z uvedených způsobů podporuje a je pouze otázkou konfigurace, jaká implementace se použije.

Výhody: snadná implementace, nenáročná kontrola změny dat a roll-back pouze v případě konfliktu

Nevýhody: všechny konkurentní transakce (myšleno nad jednou datovou jednotkou, např. tabulkou) musejí používat optimistické zamykání, není vždy možné provádět změny v datovém modelu a tedy přidávat nové sloupce (není možné vždy použít třetí variantu ověřování, např. problémy s null hodnotami, desetinná čísla), není zaručena konzistence čtených dat.

Použití: vhodné pro aplikace, kde máme datový model pod kontrolou, kde nám moc nevadí nekonzistentnost dat při čtení a hlavně tam, kde nám nevadí, když se aktualizace dat neprovede. Pokud budu v UI mít složitý formulář nebo průvodce přes několik obrazovek, tak pak bych optimistické zamykání určitě nepoužil, protože uživatel by asi nebyl moc šťastný, když by si po několika minutách vkládání dat do formulářů přečetl hlášku, že data nelze uložit.

V příštím díle se zmíním o pesimistickém zamykání a dalších možnostech řešení konkurenčního přístupu k datům.

2. března 2008

Proč nemám rád Seam

V poslední době se hodně hovoří o JBoss Seamu - píší se o něm články (1, 2, 3), přednáší se o něm, u nás v práci se vedou diskuze, zda ho použít nebo ne. Mě už to prostě nedá, abych zapřemýšlel veřejně, protože bych moc rád moje názory zkonzultoval s okolním světem.

Ještě než se pustím do "přemýšlení", tak musím poznamenat, že jsem hodně ovlivněný Springem - mám tu technologii rád, nikdy mě nezklamala, ztotožňuji se s názory lidí ze SpringSource. Mám také rád Javu, protože mám možnost plné kontroly nad aplikací, když chci napsat výkonnou, škálovatelnou a robustní aplikaci.
Také musím napsat, že nemám žádnou větší zkušenost se Seamem, pouze jsem si zkoušel a procházel nějaká dema.

Co se mi na Seamu líbí?

  • výborně integruje (a opravuje) technologii JSF a pokud dnes někdo chce používat JSF, tak asi určitě se Seamem.

  • Seam framework integruje spoustu technologií dohromady v jeden kompaktní celek.

  • Seam považuji nejsilnější v prezentační vrstvě, hlavně se mi líbí možnost využití a integrace AJAXových komponent.

  • Nemůžu nezmínit rychlost vývoje, potažmo náklady na vývoj aplikace.

Co se mi na Seamu nelíbí?

  • velice mi jsou blízká "čistá", flexibilní řešení, protože člověk nikdy neví (lépe řečeno zákazník nikdy neví). Z tohoto pohledu se mi Seam moc nelíbí - z vlastní zkušenosti vím, že hodně často je potřeba ještě jedna vrstva (Facade) mezi kontrolerem a aplikační vrstvou. Dnes je in, že vše musí být POJO, ale pokud POJO má na sebe navěšeno spoustu anotací, které mi zabraňují v testování, které mě vážou k nějakému řešení, tak už to není POJO.

  • Všechno kromě snad prezentační vrstvy (ale i zde by se dalo spekulovat) jde udělat stejně dobře nebo lépe pomocí Springu. Mám na mysli zejména možnosti integrace s dalším knihovnami, možnosti konfigurace, možnosti testovatelnosti apod.

  • Spring security (dříve Acegi framework) považuji za nejlepší open-source řešení pro zajištění bezpečnosti aplikací. Seam pěkně zapojil Drools, ale i tak se to nedá srovnávat, hlavně co se týče flexibility a možností.

  • Vše je konfigurováno pomocí anotací. Někdo je má rád, někdo ne. Já jak kdy, takže mi tu chybí možnost volby. Např. konfigurace scheduleru přes anotace v Seamu mi přijde celkem hrozná.

  • Kompaktnost řešení je negativně vyvážena omezenou možností použití řešení třetích stran.

Co říci závěrem

V žádném případě nemohu říci, že Seam je špatný framework, protože to není pravda. Seam udělal resp. udělá velkou službu Java světu, protože dokáže přitáhnout lidi, kteří chtějí dělat malé až středně velké webové aplikace bez nějaké větší aplikační logiky v pozadí, kteří ale nechtějí nebo mají strach se prokousávat tolika technologiemi, které je potřeba pochopit a naučit se.

Já ale (snad) už začátečník v Javě nejsem, potřebné technologie znám, nerad vytvářím GUI, spíše mě zajímá pozadí aplikace, píši malé, středně velké až velké aplikace, které nepracují pouze s databází, které mají mnohdy složitou aplikační logiku, které mají být výkonné, robustní... A proto tedy nemám rád Seam.

Java applety a SSL

Jak jsem již dříve referoval, na jednom našem projektu používáme komponentu ImageUploader pro nahrávání dokumentů do systému. Komponenta se automaticky dle verze prohlížeče spouští jako ActiveX (pro IE) a nebo Java applet. Komunikace mezi komponentou a serverem je zabezpečena pomocí protokolu HTTPS.

Dále je důležité říci, že zákazník má vlastní certifikační autoritu, která není odvozena od žádné věhlasné věrohodné certifikační autority.

Pokud uživatel nechce, aby se mu pořád objevovala chyba, že cílová stránka má neplatný certifikát, tak je nutné importovat kořenový certifikát do lokálního úložiště důvěryhodných certifikátů na počítači daného uživatele. Tento postup je asi následující:

  1. Stáhnu si kořenový certifikát zákazníka vystavený na webu
  2. Kliknu na něj a průvodce mě provede instalací certifikátu

Postup velice jednoduchý a pro uživatele nijak komplikovaný.

Jenže je tu velké ALE - takto jednoduché je to pouze pro prohlížeč Internet Explorer. Pro Firefox je to složitější, protože má vlastní úložiště důvěryhodných certifikátů, takže je potřeba import kořenového certifikátu udělat ještě jednou zvlášť pro Firefox.

Pokud chceme používat Java Applety se zabezpečenou komunikací, tak musíme jít ještě dále, protože Java má také svoje úložiště důvěryhodných certifikátů a proto musíme kořenový certifikát vložit i sem. K tomu má Java nástroj keytool, který je sice celkem mocný, ale bez šance, že by s ním dělal normální uživatel internetu.

Co s tím? Řešením by bylo, kdyby kořenový certifikát zákazníka byl odvozen od nějaké světově věrohodné společnosti jako třeba VeriSign, Thawte. Tyto věrohodné firmy jsou již automaticky v úložištích důvěryhodných certifikačních autorit, takže by úplně odpadl import certifikátů. Jenže za to se platí a na to zákazník nemá peníze.
Dalším řešením by bylo, kdyby bylo jedno úložiště důvěryhodných certifikátů. To nevím, jak je moc reálné, takže to nemohu posoudit. Co mě ale nejvíce překvapuje, že Java resp. Java applet není schopen sdílet informace o certifikátech s prohlížečem, ve kterém běží?

Přijde mi tento postup natolik uživatelsky nepřívětivý (navíc ještě ve srovnání s technologií ActiveX), že se spíše ptám sám sebe, kde jsem udělal chybu já. Z mého pohledu je to další důvod pro mé tvrzení, že Java applety se moc nepovedly a už se nemůžu dočkat až bude něco lepšího, snad JavaFX.

Pokud mi můžete v tomto směru poradit, tak budu moc rád.

28. února 2008

Způsoby konfigurace Springu

Když se mluví o Springu, tak to má hned každý spojený s tím, že se vše konfiguruje pomocí XML. Pravděpodobně je to kvůli tomu, že opravdu v minulosti (do verze 2.0) nebyla jiná schopná možnost konfigurace, ale to již dneska v žádném případě neplatí.

Jakými způsoby můžeme tedy konfigurovat springovské aplikace?

XML

Vždy aspoň trochu té konfigurace v XML budeme potřebovat, minimálně říci, že budeme konfigurovat např. pomocí anotací. Já osobně mám konfiguraci v XML celkem rád, protože vše mám vytažené na jedno místo, hned vidím všechny ty možné závislosti. V porovnání s anotacemi nemusím skákat mezi třídami a zjišťovat, jak je to vše vlastně propojené. To má podle mě také výhodu s ohledem na úpravu konfigurace. Na druhou stranu musím uznat, že někdy je to "až moc upovídané" - to se částečně zlepšilo s nástupem namespaců. Nejvíce mi to přijde upovídané ve webové vrstvě okolo kontrolerů, tak jsem tuto část aplikace začal konfigurovat pomocí anotací.

Anotace

Od druhé verze Springu je možné používat anotace. Anotace jsou v poslední době "sexy", takže tento styl se bude využívat asi hodně často. Spring se také snaží držet hesla "convention over configuration", což ve spojení s anotacemi vytváří velice rychlý a efektivní způsob konfigurace. Jak už jsem zmiňoval, velice se mi toto osvědčuje pro webovou vrstvu aplikace.

Java konfigurace

Tento způsob konfigurace není standardní součástí Spring frameworku, ale je vyvíjen bokem jako Spring Java Configuration Project. Tento způsob bych asi použil tehdy, když bych potřeboval mít dynamicky měnící se konfiguraci, tj. za běhu např. měnit nastavení parametrů připojení k databázi. Výhodou určitě také je to, že vše je v Javě - máme doplňování kódu, kontroly syntaxe a všeho možného, refaktoring.
Zdá se mi ale, že tento projekt se nějak zastavil. Pamatuji si na několik přednášek na konferenci SpringOne v červnu minulého roku, kde toto prezentovali jako novinku a zajímavou možnost do budoucna. Je o devět měsíců později a projekt je pořád ve stejném stavu. Myslím si, že přeci těch způsobů konfigurace je celkem dost a že malinkato se to překrývá s projektem Spring dynamic modules.

Properties

Hned na začátku říkám, že nemám na mysli využití PropertyPlaceholderConfigurer, ale PropertiesBeanDefinitionReader . Jedná se tedy o způsob konfigurace pomocí properties souborů.
Tento způsob konfigurace je ve Springu už asi jen z historických důvodů, na nových projektech tento způsob už asi nikdo nepoužije.


Na závěr bych dodal, že jednotlivé způsoby konfigurace lze libovolně křížit, pro určitou část můžeme použít anotace, pro jinou XML apod.
Volba způsobu konfigurace závisí na každém z nás, každý preferuje jiný způsob. Proto mi přijde celkem nefér, že se často vytýká Springu jeho upovídanost, protože je to každého věc a pokud budu chtít, tak té konfigurace bude opravdu minimum.

Články k příspěvku:
More on Java Configuration
Spring Java Configuration Moving Ahead

16. ledna 2008

Bezpečnostní problémy webových aplikací

Již před pár lety naše firma vytvořila aplikaci pro administraci LDAP adresáře jedné nejmenované pojišťovny. Nyní si pojišťovna nechala udělat bezpečnostní audit - nejen na naší aplikaci, ale obecně na celé své řešení spojené s adresářovými službami.
Některé připomínky mě více či méně překvapily, posuďte sami (jen pro přesnost musím uvést, že s většinou uvedených problémů naše aplikace neměla problémy):

  • problém jménem Cross-site scripting (2) (XSS). Tento způsob podvržení není asi dobré podceňovat, protože možnosti útoků jsou skoro nekonečné. Jako vhodné řešení (poměr námaha vs. úspěšnost) se mi jeví převádět všechny podezřelé položky (takže vlastně všechny) na HTML entity. Zde nestačí pouze kontrolovat resp. převádět položky zadané uživatelem, ale ideálně i položky z LDAPu nebo databáze.

  • CRLF injection, SQL injection

  • správa sessions - po každém přihlášení by se měla zrušit stávající session (která byla vytvořena v moment přístupu k aplikaci) a vytvořit nová session. Po odhlášení vždy session zneplatnit.

  • ošetření chybových stavů - chybová hlášení by neměla být natolik detailní, aby z nich bylo možné vyčíst údaje vhodné pro další typy útoků. Např. neuvádět detailní popis služby, která spadla, neuvádět jména a verze komponent, kde nastal problém apod.

  • slabá hesla - auditor zkoušel namátkou odhadnout hesla uživatelů a zjistil, že 364 uživatelů má heslo "12345678", 12 uživatelů pak "87654321"!