LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> Java na web X. - Autentizace a autorizace

Webová aplikace potřebuje své uživatele a mezi nimi je potřeba nějakým způsobem rozlišovat. V dnešním díle se budeme věnovat dvoum pojmům – autentizaci a autorizaci.

16.7.2013 12:00 | Petr Horáček | Články autora | přečteno 7544×

V minulém díle jsme si aplikaci rozšířili o databázi, dnes přijde na řadu správa uživatelů a jejich přístupů. Nejdříve se seznámíme se základními pojmy, poté si popíšeme konfiguraci autentizace a autorizace, nakonec si opět vylepšíme naši aplikaci.

Autentizace a autorizace

Tyto dva pojmy sice vypadají velmi podobně, ale je velmi důležité si je neplést. Autentizace označuje zjištění identity uživatele, nejčastěji pomocí přihlášení. Autorizace určuje, které akce bude moci uživatel vykonat a které nikoliv.

Ukládání uživatelů

Asi bude dobré začít u samotného „skladování“ uživatelů, pro tyto účely můžeme použít například XML soubor nebo SQL databázi. V obou případech musíme nakonfigurovat tzv. Realm odkazující na Resource.

Realm (česky říše) je seznam všech uživatelů a skupin náležících k jedné aplikaci (nebo skupině aplikací).

UserDatabaseRealm

Při použití XML si ulehčíme práci spojenou s konfigurací databáze, pro pár stálých uživatelů (například správce) je toto řešení dostačující, hlavní nevýhoda tkví v nutnosti restartování aplikace pro načtení nově zapsaných uživatelů.

Konfigurace UserDatabaseRealm se nachází v souboru Tomcatu server.xml hned po instalaci (pozn.: lze ji ale vložit i do souboru context.xml aplikace). Skládá se ze dvou částí, první je Resource (vnořený do tagu GlobalNamingResources) odkazující na soubor conf/tomcat-users.xml ve složce Tomcatu.

<Resource auth="Container" description="Databáze uživatelů" 
    factory="org.apache.catalina.users.MemoryUserDatabaseFactory" 
    name="UserDatabase" 
    pathname="conf/tomcat-users.xml" type="org.apache.catalina.UserDatabase"/>

Druhou částí je tag Realm (vnořený do tagu <Realm className="org.apache.catalina.realm.LockOutRealm">) odkazující na zdroj (Resource) a definující název pomocí kterého budeme k uživatelům přistupovat.

<Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase"/>

Obsah souboru tomcat-users.xml má standardně zakomentován všechno nastavení, po úpravě může vypadat například takto:

<?xml version='1.0' encoding='utf-8'?>
<tomcat-users>
  <role rolename="role1"/>
  <user username="uzivatel" password="heslo" roles="role1"/>
</tomcat-users>

Tagem role vytvoříme novou roli, v tagu user vytvoříme nového uživatele, přiřadíme mu uživatelské jméno, heslo a roli.

JDBCRealm

V případě použití databáze pro ukládání uživatelů nás sice čeká poněkud delší příprava, poté ale budeme moci snadno a dynamicky spravovat více uživatelů.

Začněme s tím, jak by měla vypadat databáze pro ukládání uživatelů a rolí. a) Pro naše účely je potřeba alespoň jedna tabulka (může se nacházet ve společené databázi s dalšími daty aplikace) se jménem, heslem a rolí uživatele, řešení s jednou tabulkou nám ale dovoluje přiřazení jediné role na uživatele. b) Lepším řešením je vytvoření dvou tabulek. V první z nich budeme ukládata uživatele a hesla, v druhé budeme párovat uživatele s rolemi.

Když už máme databázi vytvořenou, můžeme přikročit ke konfiguraci Realm-u, ten je stejně jako UserDatabaseRealm možné vložit do souborů context.xml i server.xml.

a) Můžeme buď nakonfigurovat Realm a Resource v jednom tagu:

<Realm className="org.apache.catalina.realm.JDBCRealm"
      driverName="org.gjt.mm.mysql.Driver"
      connectionURL="jdbc:mysql://localhost/databaze?user=uzivatel&amp;password=heslo"
       userTable="users" userNameCol="username" userCredCol="password"
       userRoleTable="user_roles" roleNameCol="rolename"/>

b) Pokud ale už máte Resource s přístupem k databázi vytvořený, je možné se na něj z Realm-u pouze odkázat:

<Realm className="org.apache.catalina.realm.DataSourceRealm"
   dataSourceName="jdbc/mysql"
   userTable="users" userNameCol="username" userCredCol="password"
   userRoleTable="user_roles" roleNameCol="rolename"/>

Šifrování

Hesla by neměla být ukládána jako prostý text, ale v šifrované podobě. Tomcat standardně podporuje tři hashovací algoritmy: SHA, MD2 a MD5. Pro jejich použití stačí do tagu Realm přidat atribut digest a jako jeho parametr dosadit název algoritmu (např. digest="MD5").

Autorizace

Nyní zpět k autorizaci, ta se v Tomcatu konfiguruje jako omezení přístupu k jednotlivým servletům pouze pro určité role.

web.xml

První možností konfigurace autorizací je pomocí tagu security-constraintv souboru web.xml aplikace:

<security-constraint>
    <display-name>Private Security Constraint</display-name>
    <web-resource-collection>
        <web-resource-name>Protected Area</web-resource-name>
        <url-pattern>/private/*</url-pattern>
        <url-pattern>/administration</url-pattern>
        <http-method>GET</http-method>
        <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
        <role-name>user</role-name>
        <role-name>admin</role-name>
    </auth-constraint>
</security-constraint>

Tag url-pattern zde určuje adresy, ke kterým se toto opatření vztahuje. Http-method určuje HTTP metody na kterých se má ochrana používat (pokud nazadáte žádnou, bude použita na všechny). Role-name určuje role, které mají povolený přístup. Pokud chcete používat na chráněných místech SSL protokol, můžete do security-constraint přidat tyto tagy:

<user-data-constraint>
    <transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>

Anotace

Druhou možností konfigurace autorizací je definování autorizace pomocí anotace přímo u servletu.

@ServletSecurity(
    @HttpConstraint(rolesAllowed = {"user"}, transportGuarantee = TransportGuarantee.CONFIDENTIAL))

Touto anotací povolíme přístup k servletu pouze uživatelům s rolí user, při spojení bude navíc vynuceno šifrování dat pomocí SSL.

Autentizace

Tomcat podstatně ulehčuje starosti kolem autentizace uživatelů, po minimální konfiguraci totiž sám kontroluje zda se daný uživatel v databázi nachází a zda jsou údaje správné. Je zde možné použít čtyři metody přihlašování: HTTP BASIC, HTTP DIGEST, HTTPS CLIENT a vlastní formuláře.

Konfigurace se provádí v souboru web.xml a vypadá následovně:

<login-config>
  <auth-method>BASIC</auth-method>
  <realm-name>Realm</realm-name>
</login-config>

Touto konfigurací nastavíme jako způsob přihlašování BASIC (podobně je to i s DIGEST a CLIENT), při konfiguraci vlastního formuláře je kód o trochu delší:

<login-config>
    <auth-method>FORM</auth-method>
    <realm-name>Realm</realm-name>
    <form-login-config>
        <form-login-page>/prihlaseni</form-login-page>
        <form-error-page>/chybaprihlaseni</form-error-page>
    </form-login-config>
</login-config>

Zde je nutné navíc nastavit stránku s přihlašovacím formulářem a s hlášením o neúspěchu.

Úprava aplikace

Přejděme už k úpravě samotné aplikace. Uživatele budeme ukládat do již vytvořené databáze, hesla budou zahashována algoritmem MD5, autentizace bude probíhat pomocí HTML formuláře a každý uživatel bude mít přístup pouze ke svým zápiskům.

Databáze

Začněme s úpravou databáze, přidáme do ní dvě nové tabulky – users a user_roles.

Otevřete tedy v NetBeans spojení s naší databázi (vytvořenou v minulém díle) a odešlete první příkaz pro vytvoření tabulky users (username bude primární klíč, password bude řetězec o délce 32, což je délka hashe MD5):

create table users (
  username varchar(15) not null primary key,
  password varchar(32) not null
);

Druhým příkazem vytvořte tabulku user_roles (pár username-rolename bude sloužit jako primární klíč):

create table user_roles (
  username varchar(15) not null,
  rolename varchar(15) not null,
  primary key (username, rolename)
);

Rovnou si vytvoříme i nového uživatele. Klikněte na tabulku users a zvolte View Data, do zobrazené tabulky přidejte nový řádek. Jako username zadejte např. „uzivatel“. Heslo si přeložte do MD5 (například zde: http://www.adamek.biz/md5-generator.php, „heslo“ → 955db0b81ef1989b4a4dfeae8061a9a6) a vložte do sloupce password, přidání nového řádku potvrďte. Nyní klikněte na tabulku user_roles, zvolte View Data a vložte nový řádek. Username zadejte „uzivatel“ a role „user“. Teď je nový uživatel připraven k použití.

Poslední změnou na databázi bude přidání nového sloupce autor do tabulky zapisky. Klikněte tedy pravým tlačítkem na tuto tabulku a zvolte Add Column, jméno (name) sloupce nastavte na autor, type varchar a size 15, nakonec odoznačte možnost null a potvrďte formulář.

Realm

Databázi máme upravenou a můžeme se dát do konfigurace Realmu, otevřete tedy context.xml aplikace a vložte do těla tagu Context tento kód:

<Realm className="org.apache.catalina.realm.DataSourceRealm"
    dataSourceName="jdbc/mysql" digest="MD5" localDataSource="true"
    userTable="users" userNameCol="username" userCredCol="password"
    userRoleTable="user_roles" roleNameCol="rolename"/>

Tím nastavíme jako zdroj Realm-u minule vytvořený Resource, hashování hesel na MD5, tabulka uživatelů má název users, sloupec se jmény username, spoupec s hesly password, tabulka rolí user_roles a sloupec s rolemi rolename.

UpravaZapisku.java

Nyný můžeme upravit třídu UpravaZapisku. Abychom zajistili, že bude každý uživatel moci přistupovat pouze ke svým záznamům, přidáme ke všem dotazům určení autora:

...
    public List<Zapisek> getZapisky(String uzivatel) throws SQLException {
        ...
        try {
            String query = "SELECT * FROM zapisky WHERE autor = ?";            
            connection = getConnection();            
            stmt = connection.prepareStatement(query);        
            stmt.setString(1, uzivatel);
            rs = stmt.executeQuery();
            
        ...
    }
    
    public Zapisek getZapisek(int id, String uzivatel) throws SQLException {
        ...
        try {
            String query = "SELECT * FROM zapisky WHERE id = ? AND autor = ?";            
            connection = getConnection();            
            stmt = connection.prepareStatement(query); 
            stmt.setInt(1, id);
            stmt.setString(2, uzivatel);
            rs = stmt.executeQuery();
            
        ...
    }
    
    public void setZapisek(int id, String nadpis, String obsah, String uzivatel) throws SQLException {
        ...       
        try {
            String query = "UPDATE zapisky SET nadpis = ?, obsah = ? WHERE id = ? AND autor = ?";            
            connection = getConnection();            
            stmt = connection.prepareStatement(query); 
            stmt.setString(1, nadpis);
            stmt.setString(2, obsah);
            stmt.setInt(3, id);
            stmt.setString(4, uzivatel);
            stmt.executeUpdate();
           
        ...
    }
    
    public void addZapisek(String nadpis, String obsah, String uzivatel) throws SQLException {
        ...
        try {
            String query = "INSERT INTO zapisky (nadpis, obsah, autor) VALUES (?, ?, ?)";            
            connection = getConnection();            
            stmt = connection.prepareStatement(query); 
            stmt.setString(1, nadpis);
            stmt.setString(2, obsah);
            stmt.setString(3, uzivatel);
            stmt.executeUpdate();
            
        ...
    }
    
    public void removeZapisek(int id, String uzivatel) throws SQLException {
        ...
        try {
            String query = "DELETE FROM zapisky WHERE id = ? AND autor = ?";            
            connection = getConnection();            
            stmt = connection.prepareStatement(query); 
            stmt.setInt(1, id);
            stmt.setString(2, uzivatel);
            stmt.executeUpdate();
            
        ...
    }  
}

Autorizace

Přejděme ke konfiguraci autorizace a úpravě servletu. Protože máme pouze jediný servlet, nepoužijeme web.xml, ale anotaci. Přidejte tedy tento kód (povolující přístup pouze roli user) nad servlet Controller:

@ServletSecurity(
    @HttpConstraint(rolesAllowed = {"user"}))

Abychom rozeznali jednotlivé uživatele přistupující k servletu, přidejte do metod doPost a doGet tento kód:

String uzivatel = request.getRemoteUser();

Nakonec upravte všechna volání databáze tak, aby jako poslední parametr předávaly jméno přihlášeného uživatele:

...
List<Zapisek> zapisky = databaze.getZapisky(uzivatel);
...
Zapisek zapisek = databaze.getZapisek(id, uzivatel);
...
databaze.addZapisek(nadpis, obsah, uzivatel);
...
databaze.setZapisek(id, nadpis, obsah, uzivatel);
...
databaze.removeZapisek(id, uzivatel); 
...

Autentizace

Už máme nastavené úložiště uživatelů i autorizace, nyní zbývá už jen nastavit autentizaci. Začneme vytvořením vlastního přihlašovacího formuláře. Abychom nemuseli vytvářet druhý (veřejný) controller, vytvoříme soubor prihlasit.jsp ve veřejné složce Web Pages a vložíme do něj tento kód:

<%@page contentType="text/html" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib tagdir="/WEB-INF/tags" prefix="m" %>

<m:Base titulek="Zápisky">
    <h1>Zápisník - přihlášení</h1>
    
    <form method="POST" action="j_security_check" >
        <input type="hidden" name="id" value="${zapisek.id}" />
        <label for="jmeno">Přihlašovací jméno</label><br>
        <input type="text" name="j_username" id="jmeno" />
        <br>
        <label for="heslo">Heslo</label><br>
        <input type="password" name="j_password" id="heslo" />
        <br>
        <input value="Přihlásit" type="submit" />
    </form>

    <c:if test="${param.upozorneni}">
        <span>Zadané údaje nejsou platné.</span>
    </c:if>
</m:Base>

Abychom vytvořili přihlašovací formulář spravovaný Tomcatem, je potřeba jen velice málo: Formulář musí mít za atribut action dosazený parametr j_security_check, vstup pro jméno musí být označen j_username a heslo j_password. Navíc je zde upozornění na špatně vyplněné údaje.

Zbývá už jen konfigurovat přihlašování v souboru web.xml. Otevřete tedy tento soubor, přesuňte se do karty Security a rozbalte Login Configuration. Nyní označte možnost Form, login page nastavte na /prihlasit.jsp a error page na /prihlasit.jsp?upozorneni=true, Realm name zadejte libovolné.

Závěr

To je vše, nyní můžete aplikaci spustit, přihlásit se a vkládat nové zápisky. V příštím díle se budeme věnovat neoddělitelné části vývoje (a provozu) aplikací – logování, testování a debuggování.

Zdrojové kódy aplikace naleznete na GitHubu: https://github.com/PetrHoracek/JavaNaWeb

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

14.11.2017 16:56 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tradičně první čtvrtek před třetím pátkem v měsíci: 16. listopadu od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.11.2017 11:06 /Redakce Linuxsoft.cz
PR: 4. ročník odborné IT konference na téma Datová centra pro business proběhne již ve čtvrtek 23. listopadu 2017 v konferenčním centru Vavruška, v paláci Charitas, Karlovo náměstí 5, Praha 2 (u metra Karlovo náměstí) od 9:00. Konference o návrhu, budování, správě a efektivním využívání datových center nabídne odpovědi na aktuální a často řešené otázky, např Jaké jsou aktuální trendy v oblasti datových center a jak je využít pro vlastní prospěch? Jak zajistit pro firmu či jinou organizaci odpovídající služby datových center? Podle jakých kritérií vybrat dodavatele služeb? Jak volit součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně spravovat datové centrum? Jak eliminovat možná rizika? apod.
Přidat komentář

13.9.2017 8:00 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt – tentokrát netradičně v pondělí: 18. září od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

3.9.2017 20:45 /Redakce Linuxsoft.cz
PR: Dne 21. září 2017 proběhne v Praze konference "Mobilní řešení pro business". Hlavní tématy konference budou: nejnovější trendy v oblasti mobilních řešení pro firmy, efektivní využití mobilních zařízení, bezpečnostní rizika a řešení pro jejich omezení, správa mobilních zařízení ve firmách a další.
Přidat komentář

15.5.2017 23:50 /František Kučera
Máš rád svobodný software a hardware nebo se o nich chceš něco dozvědět? Zajímá tě DIY, CNC, SDR nebo morseovka? Přijď na sraz spolku OpenAlt, který se bude konat ve čtvrtek 18. května od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

12.5.2017 16:42 /Honza Javorek
PyCon CZ, česká konference o programovacím jazyce Python, se po dvou úspěšných ročnících v Brně bude letos konat v Praze, a to 8. až 10. června. Na konferenci letos zavítá např. i Armin Ronacher, známý především jako autor frameworku Flask, šablon Jinja2/Twig, a dalších projektů. Těšit se můžete na přednášky o datové analytice, tvorbě webu, testování, tvorbě API, učení a mentorování programování, přednášky o rozvoji komunity, o použití Pythonu ve vědě nebo k ovládání nejrůznějších zařízení (MicroPython). Na vlastní prsty si můžete na workshopech vyzkoušet postavit Pythonem ovládaného robota, naučit se učit šestileté děti programovat, efektivně testovat nebo si v Pythonu pohrát s kartografickým materiálem. Kupujte lístky, dokud jsou.
Přidat komentář

2.5.2017 9:20 /Eva Rázgová
Putovní konference československé Drupal komunity "DrupalCamp Československo" se tentokrát koná 27. 5.2017 na VUT FIT v Brně. Můžete načerpat a vyměnit si zkušenosti z oblasti Drupalu 7 a 8, UX, SEO, managementu týmového vývoje, využití Dockeru pro Drupal a dalších. Vítáni jsou nováčci i experti. Akci pořádají Slovenská Drupal Asociácia a česká Asociace pro Drupal. Registrace na webu .
Přidat komentář

1.5.2017 20:31 /Pavel `Goldenfish' Kysilka
PR: 25.5.2017 proběhne v Praze konference na téma Firemní informační systémy. Hlavními tématy jsou: Informační systémy s vlastní inteligencí, efektivní práce s dokumenty, mobilní přístup k datům nebo využívání cloudu.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

5.12.2017 11:50 / Thomas
kitchen renovations

18.9.2017 14:37 / Rojas
high security vault

15.9.2017 7:33 / Wilson
new zealand childcare jobs

31.8.2017 12:11 / Jaromir Obr
Re: ukůládání dat ze souboru

30.7.2017 11:12 / Jaromir Obr
Národní znaky

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2017) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze