LINUXSOFT.cz Přeskoč levou lištu

ARCHIV



   

> 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 10387×

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ů

28.11.2018 23:56 /František Kučera
Prosincový sraz spolku OpenAlt se koná ve středu 5.12.2018 od 16:00 na adrese Zikova 1903/4, Praha 6. Tentokrát navštívíme organizaci CESNET. Na programu jsou dvě přednášky: Distribuované úložiště Ceph (Michal Strnad) a Plně šifrovaný disk na moderním systému (Ondřej Caletka). Následně se přesuneme do některé z nedalekých restaurací, kde budeme pokračovat v diskusi.
Komentářů: 1

12.11.2018 21:28 /Redakce Linuxsoft.cz
22. listopadu 2018 se koná v Praze na Karlově náměstí již pátý ročník konference s tématem Datová centra pro business, která nabídne odpovědi na aktuální a často řešené otázky: Jaké jsou aktuální trendy v oblasti datových center a jak je optimálně využít pro vlastní prospěch? Jak si zajistit odpovídající služby datových center? Podle jakých kritérií vybírat dodavatele služeb? Jak volit vhodné součásti infrastruktury při budování či rozšiřování vlastního datového centra? Jak efektivně datové centrum spravovat? Jak co nejlépe eliminovat možná rizika? apod. Příznivci LinuxSoftu mohou při registraci uplatnit kód LIN350, který jim přinese zvýhodněné vstupné s 50% slevou.
Přidat komentář

6.11.2018 2:04 /František Kučera
Říjnový pražský sraz spolku OpenAlt se koná v listopadu – již tento čtvrtek – 8. 11. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma umění a technologie, IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

4.10.2018 21:30 /Ondřej Čečák
LinuxDays 2018 již tento víkend, registrace je otevřená.
Přidat komentář

18.9.2018 23:30 /František Kučera
Zářijový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 20. 9. 2018 od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5). Tentokrát bez oficiální přednášky, ale zato s dobrým jídlem a pivem – volná diskuse na téma IoT, CNC, svobodný software, hardware a další hračky.
Přidat komentář

9.9.2018 14:15 /Redakce Linuxsoft.cz
20.9.2018 proběhne v pražském Kongresovém centru Vavruška konference Mobilní řešení pro business. Návštěvníci si vyslechnou mimo jiné přednášky na témata: Nejdůležitější aktuální trendy v oblasti mobilních technologií, správa a zabezpečení mobilních zařízení ve firmách, jak mobilně přistupovat k informačnímu systému firmy, kdy se vyplatí používat odolná mobilní zařízení nebo jak zabezpečit mobilní komunikaci.
Přidat komentář

12.8.2018 16:58 /František Kučera
Srpnový pražský sraz spolku OpenAlt se koná ve čtvrtek – 16. 8. 2018 od 19:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát jsou tématem srazu databáze prezentaci svého projektu si pro nás připravil Standa Dzik. Dále bude prostor, abychom probrali nápady na využití IoT a sítě The Things Network, případně další témata.
Přidat komentář

16.7.2018 1:05 /František Kučera
Červencový pražský sraz spolku OpenAlt se koná již tento čtvrtek – 19. 7. 2018 od 18:00 v Kavárně Ideál (Sázavská 30, Praha), kde máme rezervovaný salonek. Tentokrát bude přednáška na téma: automatizační nástroj Ansible, kterou si připravil Martin Vicián.
Přidat komentář

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

> Poslední diskuze

31.7.2023 14:13 / Linda Graham
iPhone Services

30.11.2022 9:32 / Kyle McDermott
Hosting download unavailable

13.12.2018 10:57 / Jan Mareš
Re: zavináč

2.12.2018 23:56 / František Kučera
Sraz

5.10.2018 17:12 / Jakub Kuljovsky
Re: Jaký kurz a software by jste doporučili pro začínajcího kodéra?

Více ...

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