V předchozím článku jsme vytvořili správce uživatelů. V tomto článku si ukážeme, jak zajistit, aby instance třídy z předchozího článku byla vytvářena a likvidována společně s aplikací. Instanci vytvoříme pomocí posluchače událostí aplikace (ServletContextListener). Dále si předvedeme, jak zpracovat data z přihlašovacího formuláře a uděláme si malé shrnutí.

Instance třídy z předchozího článku musí být dostupná v rámci celé aplikace. Bude registrována v objektu application jako atribut aplikace. Otázka spíše je, kdy ji vytvořit a zaregistrovat. Musí to být v okamžiku, kdy je vytvářena aplikace (instance typu ServletContext).

Pro aplikaci můžeme zaregistrovat posluchače událostí (ukázkový kód). Posluchač událostí aplikace (událost nastane při změně stavu) je informován o inicializování (spuštění) a zlikvidování (ukončení) aplikace. Posluchač událostí je instance třídy, která implementuje rozhraní ServletContextListener. Rozhraní obsahuje dvě metody:

  • public void contextDestroyed(ServletContextEvent sce) – je zavolána v momentě, kdy aplikace ukončuje svoji činnost
  • public void contextInitialized(ServletContextEvent sce) – je zavolána v momentě, kdy je aplikace inicializována

Parametrem obou metod je instance třídy ServletContextEvent, která má metodu public ServletContext getServletContext(). Tato metoda nám vrátí referenci na aplikaci, která událost vyslala.

Konfigurační údaje zapíšeme do web.xml pomocí elementu context-param, který obsahuje potomky param-name a param-value. Elementy mají stejný význam jako při zadávání parametrů pro filtry, se kterými jsme se již setkali. Rozhraní ServletContext má k dispozici metodu public java.lang.String getInitParameter(java.lang.String name), která nám vrátí hodnotu parametru odpovídající jménu parametru předanému metodě jako parametr. Vytvoříme třídu posluchače:

public class ApplicationListener implements ServletContextListener
{
public ApplicationListener()
{
  super();
}
public void contextDestroyed(ServletContextEvent sce)
{
  ServletContext application = sce.getServletContext();
  UserManager manager = (UserManager) application.getAttribute(Constants.USERMANAGER);
  try
  {
    if (manager != null)
    {
      application.removeAttribute(Constants.USERMANAGER);
      manager.closeConnection();
    }
  }
  catch (SQLException e)
  {
  }
}
public void contextInitialized(ServletContextEvent sce)
{
  ServletContext application = sce.getServletContext();
  UserManager manager = new UserManager();
  manager.setConnectionName(application.getInitParameter(„connectionName“));
  manager.setConnectionPassword(application.getInitParameter(„connectionPassword“));
  manager.setConnectionURL(application.getInitParameter(„connectionURL“));
  manager.setDigest(application.getInitParameter(„digest“));
  manager.setDriverName(application.getInitParameter(„driverName“));
  manager.setRoleNameCol(application.getInitParameter(„roleNameCol“));
  manager.setUserCredCol(application.getInitParameter(„userCredCol“));
  manager.setUserNameCol(application.getInitParameter(„userNameCol“));
  manager.setUserRoleTable(application.getInitParameter(„userRoleTable“));
  manager.setUserTable(application.getInitParameter(„userTable“));
  try
  {
    manager.openConnection();
    application.setAttribute(Constants.USERMANAGER, manager);
    try
    {
      application.setAttribute(Constants.LOGINFORM,“http:/“ +
        application.getResource(„/“).getPath() +
        application.getInitParameter(„loginForm“));
      application.setAttribute(Constants.ERRORPAGE,“http:/“ +
        application.getResource(„/“).getPath() +
        application.getInitParameter(„loginError“));
    }
    catch (java.net.MalformedURLException e)
    {}
  }
  catch (SQLException e)
  {
    application.log(„Nelze inicializovat managera uživatelů. Autentizace nebude fungovat!“, e);
  }
  catch (ClassNotFoundException e)
  {
    application.log(„Problém s ovladačem pro databázi. Autentizace nebude fungovat!“, e);
  }
}
}

V metodě public void contextInitialized(ServletContextEvent sce) přečtu všechny potřebné parametry aplikace a nastavím je jako atributy. Ve web.xml bude pro každý parametr element context-param vypadat asi takto:

<context-param>
    <param-name>userTable</param-name>
    <param-value>usersx</param-value>
</context-param>

Kromě parametrů, které budou odpovídat atributům JDBCRealm, musíme přidat také dva další atributy, které udávají přihlašovací formulář (parametr jménem loginForm) a stránku oznamující uživateli chybné přihlášení (parametr jménem loginError).

Zbývá nakonfigurovat posluchače. K tomu slouží element listener v souboru web.xml. Element je rodičovským elementem elementu listener-class, který obsahuje název třídy posluchače. Do web.xml přidáme:

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

Podobným způsobem lze vytvořit posluchače událostí session (rozhraní HttpSessionListener) nebo HTTP požadavku (rozhraní ServletRequestListener).

Zpracování dat z přihlašovacího formuláře

Standardní přihlašovací formulář pro autentizaci uživatelů v TomCatu musí obsahovat formulář s polem s názvem j_username a j_password. Skript zpracovávající data z formuláře (atribut action) je pseudo-název j_security_check. Odeslání formulářových dat na j_security_check necháme ověřit uživatele.

Žádný skript jménem j_security_check ovšem neexistuje, čímž narážíme na první malý problém. Kód zpracovávající přihlašovací údaje od uživatele musíme napsat sami a přihlašovací formulář musí mít atribut action nastaven na náš servlet nebo JSP. V úvodním článku jsem sliboval, že dodáme třídy, které vytvoříme, vyměníme jen soubor web.xml a upravíme kód určený pro registraci uživatele. Žádné jiné změny jsme dělat neměli. Bohužel, zde je první případ, kdy budeme muset zasáhnout do aplikace, ve které chceme použít naše třídy pro autentizaci uživatelů. Budeme muset opravit atribut action přihlašovacího formuláře.

Při zpracování dat z přihlašovacího formuláře jednoduše zavoláme metodu login našeho správce uživatelů. Vrátí-li metoda null, uživatel není správně autentizován a nebude považován za přihlášeného, bude přesměrován na chybovou stránku. V opačném případě bude principal vrácený metodou zapsán do session a uživatel je přesměrován na adresu, na kterou se původně odkazoval. Zdrojový text:

authentication.UserManager Core
    = (authentication.UserManager)application.getAttribute
    (authentication.Constants.USERMANAGER);
String name = request.getParameter(„j_username“);
String password = request.getParameter(„j_password“);
if ((name == null) || (password == null))
{
  ((HttpServletResponse) response).sendRedirect
      ((String)application.getAttribute
      (authentication.Constants.LOGINFORM));
}
authentication.MyPrincipal principal
    = Core.login(name, password);
if (principal != null)
{
  session.setAttribute(authentication.Constants.USER,
      principal);
  session.setAttribute(authentication.Constants.AUTHMETHOD,
      HttpServletRequest.FORM_AUTH);
  ((HttpServletResponse) response).sendRedirect((String)session.getAttribute(authentication.Constants.REDIRECT));
}
else
{
  ((HttpServletResponse) response).sendRedirect((String)
    application.getAttribute
    (authentication.Constants.ERRORPAGE));
}

Zpracování dat z registračního formuláře – registrace uživatele

V prvním článku jsem psal, že bude nutné měnit zdrojový text servletu nebo JSP, který zpracovává registrační informace. V případě, že registrace bude úspěšná, je nutné uživatele přihlásit zavoláním metody login, která nám vrátí principala uživatele, kterého zapíšeme do session. Druhá možnost je vytvoření principala samostatně a zapsání jej do session.

Princip autentizace – shrnutí

A jsme v podstatě hotovi. Chráněná zóna je dána působností filtru AuthenticationFilter. Jeho působnost je dána konfigurací filtru ve web.xml. Přiblížit celý princip může diagram, který popisuje činnosti při požadavku uživatele na nějaký dokument v chráněné zóně:

Znázornění činnosti při příchodu HTTP požadavku
Znázornění činnosti při příchodu HTTP požadavku (plná velikost, cca 19 kB)

V případě, že bude uživatel přesměrován na přihlašovací stránku (v diagramu činností), musí se přihlásit. Přihlášení spočívá ve vyplnění přihlašovacího jména a hesla do přihlašovacího formuláře a odeslání formuláře ke zpracováni. Zpracování přihlašovacích dat z přihlašovacího formuláře popisuje následující diagram činností:

Znázornění činnosti při přihlášení uživatele
Znázornění činnosti při přihlášení uživatele (plná velikost, cca 13 kB)

V případě, že souhlasí uživatelské jméno a heslo, dojde k přesměrování požadavku na požadovaný zdroj a bude prováděna činnost znázorněná v předchozím diagramu činností.

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