|
||||||||||||||||||||||||||||||||||||||||||||||||
Menu
Distributions (131)
Software (10844)
|
Java na web X. - Autentizace a autorizaceWebová 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.
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 autorizaceTyto 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í). UserDatabaseRealmPř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.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. JDBCRealmV 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&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"). AutorizaceNyní zpět k autorizaci, ta se v Tomcatu konfiguruje jako omezení přístupu k jednotlivým servletům pouze pro určité role. web.xmlPrvní 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> AnotaceDruhou 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. AutentizaceTomcat 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 aplikacePř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ázeZač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ář. RealmDatabá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.javaNyný 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(); ... } } AutorizacePř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); ... AutentizaceUž 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ěrTo 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
|
Search Software
Search Google
|
||||||||||||||||||||||||||||||||||||||||||||||
©Pavel Kysilka - 2003-2024 | maillinuxsoft.cz | Design: www.megadesign.cz |