V minulom článku sme načali problematiku zabezpečenia web aplikácií pred neautorizovaným prístupom. Využívali sme pritom možnosti prehliadača, ktorí na požiadanie serverom zobrazil špeciálne prihlasovacie okno. Jeho úlohou bolo získať prístupové meno a heslo užívateľa. Niekedy však tento spôsob nemusí vyhovovať. Preto si dnes ukážeme ako využiť formuláre a session tracking na zabezpečenie našej aplikácie.

Autorizácia založená na formulároch

Ako vyplynulo z môjho úvodu, autorizácia založená na formulároch a sledovaní session môže nahradiť klasickú HTTP autorizáciu predstavenú v minulej časti. Na druhej strane chce to viac úsilia vytvoriť dobre a ergonomicky navrhnutú prihlasovaciu stránku. Predstavte si, že vytvárate on-line bankový internetový systém. Čo myslíte? Bude lepšie vyzvať klienta (teraz myslím zákazníka banky) na zadanie mena a hesla cez suchopárne prihlasovacie okno? Alebo ho o tieto údaje požiadate prostredníctvom pekne spracovanej prihlasovacej stránky? Okrem toho bankový systém má svoje špecifiká, ktoré vyžadujú odlišný prístup (kód grid karty a podobne). Je teda jasné, že autorizácia založená na formulároch má svoje opodstatnenie.

Implementácia tohto systému prostredníctvom servletov je viac menej priamočiara. Základom je samozrejme prihlasovacia stránka, ktorá môže byť vytvorená staticky ako HTML alebo dynamicky. Pri autentifikácii cez prihlasovací formulár je potrebné mať na pamäti, že užívateľ sa môže pokúsiť obísť prihlásenie a priamo požiadať o chránený zdroj. Pre tento prípad je potrebné vytvoriť mechanizmus, ktorý takúto činnosť odhalí a presmeruje užívateľa na prihlasovaciu stránku. Ako pridanú hodnotu je možné po prihlásení a overení užívateľa presmerovať ho na stránku o ktorú žiadal pôvodne. Takýto mechanizmus je treba vložiť do každého chráneného zdroja, respektíve vytvoriť si utilitku (triedu) a tú následne využívať.

Vytvorme si teda jednoduchú prihlasovaciu stránku login.html:

Jednoduchý prihlasovací dialóg

Potom, čo klient vloží požadované údaje, tieto sa odošlú servletu určenému na spracovanie prihlasovacích informácií. Nazvime si tento servlet LoginServlet, jeho výpis nasleduje nižšie. Servlet skontroluje správnosť vloženého mena a hesla. V reálnom nasadení sa samozrejme tieto údaje porovnávajú s databázou užívateľov a ich hesiel. V našom príklade pre zjednodušenie umožníme prístup každému, kto zadá nejaké meno a heslo. Ak sa tak stane servlet sa pokúsi presmerovať užívateľa na pôvodnú stránku o ktorú žiadal. Ak taká stránka nie je užívateľ je presmerovaný na hlavnú stránku. Môžeme ho samozrejme presmerovať aj na nejakú inú stránku. V celom procese sa využíva session objekt.

LoginServlet.java:

package interval;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class LoginServlet extends HttpServlet {
  public void doPost(HttpServletRequest req, HttpServletResponse res)
                                throws ServletException, IOException {
    res.setContentType(„text/html“);
    PrintWriter out = res.getWriter();
    // získame užívateľské meno a heslo
    String name = req.getParameter(„name“);
    String passwd = req.getParameter(„passwd“);
    // kontrola mena a hesla
    if (!allowUser(name, passwd)) {
        out.println(„<HTML><HEAD><TITLE>“);
        out.println(„Access Denied!</TITLE></HEAD>“);
        out.println(„<BODY>Nesprávne meno alebo heslo.<BR>“);
        out.println(„Skúste sa znova <A HREF=’/login.html‘>prihlásiť</A>“);
        out.println(„</BODY></HTML>“);
    }
    else {
        // prihlásenie je OK
        HttpSession session = req.getSession(true);
        session.setAttribute(„logon.isDone“, name);
        // presmerujeme užívateľa na orig. stránku
        try {
            String target = (String) session.getAttribute(„login.target“);
            if (target != null)
                res.sendRedirect(target);
                return;
        }
        catch (Exception e) { }
        // ak to nevyjde presmerujeme ho na homepage
        res.sendRedirect(req.getScheme() + „://“ +
        req.getServerName() + „:“ + req.getServerPort());
    }
  }
  protected boolean allowUser(String user, String passwd) {
    return true; // dôverujeme každému ;-)
  }
}

Ako som spomenul, je nutné vytvoriť „ochranný“ mechanizmus, aby sa každý, kto požiada o chránený zdroj, musel najprv prihlásiť. Existenciu takého mechanizmu predpokladá aj LoginServlet uvedený vyššie. Nasledujúci servlet je ukážkou implementácie ochranného mechanizmu.

ProtectedResource .java:

package interval;
import java.io.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ProtectedResource extends HttpServlet {
  public void doGet(HttpServletRequest req, HttpServletResponse res)
                        throws ServletException, IOException {
    res.setContentType(„text/plain“);
    PrintWriter out = res.getWriter();
    // získame objekt session
    HttpSession session = req.getSession(true);
    // zistíme či užívateľ sa už prihlásil
    Object done = session.getAttribute(„logon.isDone“);
    if (done == null) {
      // užívateľ nie je prihlásený
      // originálne URL uložíme do session a presmerujeme na login.html
      session.setAttribute(„login.target“,req.getRequestURL().toString());
      res.sendRedirect(req.getScheme() + „://“ +
      req.getServerName() + „:“ + req.getServerPort() +
      „/login.html“);
      return;
    }
    // ak je užívateľ prihlásený má voľnú cestu
    out.println(„…“);
  }
}

Ak to teda zhrniem, ak užívateľ požiada o chránený zdroj ProtectedResource a nie je už prihlásený, ochranný mechanizmus si zapíše požadované URL do session a presmeruje užívateľa na stránku „login.html“. Po spracovaní prihlasovacích údajov servletom LoginServlet je užívateľ opäť presmerovaný na pôvodný chránený zdroj, tentoraz je už však prihlásený. Ak sa tento proces z akéhokoľvek dôvodu neuskutoční, užívateľ je presmerovaný na homepage.

Na záver vám ponúkam všetky zdrojové kódy uvedené v tomto článku na stiahnutie.

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