V tomto článku vytvoříme jednoduchou ukázkovou aplikaci, ve které použijeme náš autentizační mechanizmus. Ukážeme si, jak autentizaci nakonfigurovat a jak ji případně vyměnit za standardní autentizaci TomCatu.

Aplikace bude velmi jednoduchá. Příchozí návštěvník se bude moci zaregistrovat a vybrat si role, pod kterými chce v systému vystupovat. Po úspěšné registraci bude mít k dispozici několik odkazů, z nichž každý jej zavede do nějaké chráněné zóny určené různým rolím.

Databáze

Nejprve vytvoříme potřebné databázové tabulky. Musíme vytvořit tabulku rolí a tabulku uživatelů. Databázi nazveme auth.

Tabulka uživatelů

Sloupec Popis Datový typ Délka
namex Uživatelská jména varchar 50
passwordx Uživatelská hesla varchar 50

Tabulka usersx

Tabulka může samozřejmě obsahovat i další sloupce.

Tabulka rolí

Sloupec Popis Datový typ Délka
rolex Názvy rolí varchar 50
namex Uživatelská jména varchar 50

Tabulka rolesx

Tabulka může samozřejmě obsahovat i další sloupce.

Webová aplikace

Po vytvoření databáze vytvoříme několik málo JSP stránek a některé dáme do různých chráněných zón. Budeme používat standardní autentizaci TomCatu. K dispozici je vám příklad, který si pro snazší představu můžete stáhnout a otestovat. V kódu nezapomeňte upravit údaje týkající se přístupu k databázi. Konkrétně jde o atributy tagu realm s názvy connectionURL, DriverName, connectionName a connectionPassword. Dále v adresáři register upravte řádky s komentářem (také se týkají přístupu k databázi). Musíte zadat vždy URL, driver, uživatelské jméno a heslo pro přístup do vaší databáze.

Všimněte si, že po zaregistrování uživatele je uživatel nepřihlášen.

Výměna autentizačního mechanizmu

Máme tedy hotovou aplikaci používající standardní autentizaci založenou na JDBCRealmu. Nyní chceme, aby se naše aplikace pomocí balíku tříd, které jsme vytvořili v předchozích článcích, chovala stejně, až na ten rozdíl, že po registraci bude uživatel přihlášen.

Vytváříme web.xml

Nejprve musíme nastavit přihlašovací formulář a stránku informující o chybě při přihlašování. Při použití standardních autentizačních prostředků bychom ve web.xml vytvořili elementy form-login-page a form-error-page. Při použití naší autentizace musíme tyto informace předat aplikaci pomocí elementu context-param. Vytvoříme parametry se jmény loginForm a loginError:

<context-param>
   <param-name>loginForm</param-name>
   <param-value>login/loginForm.jsp</param-value>
</context-param>
<context-param>
   <param-name>loginError</param-name>
   <param-value>login/error.jsp</param-value>
</context-param>

Dále musíme nakonfigurovat instanci třídy UserManager. Při použití standardních autentizačních mechanizmů bychom vytvořili v hlavním konfiguračním XML souboru v adresáři conf element realm s nastavením atributů. V našem případě opět pomocí elementů context-param ve web.xml vytvoříme parametry aplikace, které mají stejný název jako atributy elementu realm. Například místo atributu roleNameCol elementu realm vytvoříme ve web.xml parametr aplikace jménem roleNameCol (a obdobně pro všechny ostatní atributy):

<context-param>
   <param-name>rolNameCol</param-name>
   <param-value>roles</param-value>
</context-param>

Při použití realmu se nemusíme starat o to, aby byla vytvořena instance realmu. V našem případě se ale o vytvoření instance třídy UserManager musíme postarat sami. Vytvoříme posluchače událostí aplikace, jak jsme si ukázali v předchozím článku:

<listener>
    <listener-class>ApplicationListener</listener-class>
</listener>

Musíme také určit, které oblasti jsou přístupné kterým rolím. Při použití standardního autentizačního mechanizmu musíme pomocí elementu security-constraint definovat oblast a role. V našem případě provedeme nastavení chráněných zón tak, že pro každou z nich definujeme jeden filtr třídy AuthenticationFilter. Seznam rolí, které má propouštět, jsou v parametrech filtru. Filtr namapujeme na chráněnou zónu. Například:

<filter>
  <filter-name>UserFilter</filter-name>
  <filter-class>authentication.AuthenticationFilter</filter-class>
  <init-param>
    <param-name>role1</param-name>
    <param-value>zamestnanec</param-value>
  </init-param>
</filter>
<filter-mapping>
  <filter-name>UserFilter</filter-name>
  <url-pattern>/secure/user.jsp</url-pattern>
</filter-mapping>

Nesmíme zapomenout na filtr třídy RequestWrappingFilter, který musí být deklarován před filtry třídy AuthenticationFilter. Filtr musí (měl by) být namapován na celou naší WWW aplikaci.

<filter>
  <filter-name>RequestWrappingFilter</filter-name>
  <filter-class>authentication.RequestWrappingFilter</filter-class>
</filter>
<filter-mapping>
  <filter-name>RequestWrappingFilter</filter-name>
  <url-pattern>/*</url-pattern>
</filter-mapping>

Ani element security-constraint úplně nezavrhneme. Díky němu bude TomCat přesměrovávat uživatele na protokol HTTPS. Chráněná oblast musí být nastavena na masku URL, kterou chceme přesměrovávat na HTTPS. Aby byla přístupná všem rolím (o tom, kterou roli propustíme a kterou ne, rozhodují naše filtry), nebudeme vůbec vytvářet element auth-constraint:

<security-constraint>
  <web-resource-collection>
    <web-resource-name>Pokusná chráněná oblast</web-resource-name>
    <url-pattern>/*</url-pattern>
  </web-resource-collection>
  <user-data-constraint>
    <transport-guarantee>INTEGRAL</transport-guarantee>
  </user-data-constraint>
</security-constraint>

Úpravy registrace

Jak jsem se zmínil již v prvním článku, při úspěšné registraci musíme zavolat metodu login instance třídy UserManager. Tím docílíme přihlášení uživatele.

Úpravy stránky s přihlašovacím formulářem

Přihlašovací formulář má atribut action nastaven na j_security_check. Sliboval jsem, že nebudeme muset nijak změnit zdrojový text již existující aplikace (až na registraci). Bohužel, přeci jen je nutné ještě změnit atribut action na název JSP, které dodáme společně s balíkem tříd pro autentizaci. V našem případě má přihlašovací formulář název loginForm.jsp a je v adresáři login. Pro ověření správnosti uživatelského jména a hesla dodáme JSP login.jsp.

Postup úprav aplikace

Chceme-li upravit již existující aplikaci, postupujeme následovně:

  1. Dodáme balík tříd authentication, který umístíme do WEB-INF/classes.
  2. Upravíme (v podstatě celý přepíšeme) soubor web.xml podle návodu uvedeného v tomto článku.
  3. Ve skriptu, který provede zaregistrování uživatele, zajistíme přihlášení uživatele pomocí volání metody login instance třídy UserManager, která je uložena jako atribut aplikace. Samotnou registraci také upravíme. Nahradíme jí metodou register třídy UserManager.
  4. Dodáme JSP pro kontrolu přihlašovacích údajů (je popsané v předchozím článku). JSP doporučuji zkopírovat do adresáře login.
  5. Na stránce s přihlašovacím formulářem změníme atribut formuláře action na hodnotu, která odpovídá cestě k JSP vloženému v předchozím bodě.
  6. V hlavním konfiguračním souboru v adresáři conf odstraníme informaci o realmu (odstraníme celý element realm).

Pokud přesně dodržíte tento postup, získáte aplikaci používající náš autentizační mechanizmus. Můžete se přesvědčit, že se nijak nezměnila funkčnost, až na onen drobný detail, že uživatel je po registraci přihlášen. (Nezapomeňte opět v souboru web.xml doplnit parametry týkající se přístupu k databázi.)

Konečné řešení

Dosáhli jsme tedy toho, že lze nahradit autentizační mechanizmus založený na JDBCRealmu naším autentizačním mechanizmem používajícím filtry. Je potřeba dodat naše třídy, aplikaci překonfigurovat a udělat dva (registrace, přihlašování) zásahy do zdrojových textů aplikace.

Teoreticky mohou přece jen nastat problémy. Filtry zapisují některé instance jako atributy aplikace nebo session a každý atribut je identifikován svým jménem. Kdyby nastala situace, že by aplikace shodou náhod používala atributy se stejným názvem, přepisovaly by se atributy, které nastavují filtry. Myslím ale, že něčeho takového se není třeba obávat.

Odkazy a zdroje

Starší komentáře ke článku

Pokud máte zájem o starší komentáře k tomuto článku, naleznete je zde.

Žádný příspěvek v diskuzi

Odpovědět