11.7. JAAS

Az autentikációra és az autorizációra érdemes az alkalmazásszerver által nyújtott szolgáltatást, a JAAS-t (Java Authentication and Authorization Service) használni ([32]). A JAAS hagyományos működése egy webprojektben a következő: ha egy felhasználó védett erőforráshoz akar hozzáférni, akkor az alkalmazásszerver megkéri a bejelentkezésre egy arra alkalmas űrlap, ablak megjelenítésével. A védett erőforrások itt URL-ek, amelyek megtekintéséhez bizonyos jogosultságok szükségesek. Ezen oldalak listáját és a hozzáféréshez szükséges szerepeket a web.xml-ben lehet meghatározni security‑constraint tag‑ekkel.

Ugyanitt kell megadni, form‑login‑page tag‑ek közt a bejelentkezési űrlapot, ha FORM alapú autentikációt választunk. Lehetőség van még Digest vagy Basic módú bejelentkezésre is, ekkor a böngészőprogram kéri be a bejelentkezési nevet és a jelszót a felhasználótól.

Esetemben célszerűbbnek tartottam (a webes szokásokhoz igazodva) egy minden oldalon megjelenített bejelentkezési űrlapot alkalmazni. Így a felhasználónak nem kell védett erőforrásra mutató linkre kattintania ahhoz, be tudjon jelentkezni, hanem már a főoldalon ajánljuk neki ezt a lehetőséget, ugyanúgy, mint a többi menüpontot, amelyekhez nem szükséges bejelentkezés. Bejelentkezés után megjelennek a belépéshez kötött funkciók is, hasonlóan egy webes levelező- vagy más rendszerhez. (A védett oldalra való hivatkozás mindenképp szükséges a bejelentkezéshez, mert a form‑login‑page értékeként megadott oldalt közvetlenül meghívva nem működőképes a bejelentkezés.)

A webkonténer általi bejelentkeztetés hátránya, hogy hiba esetén csak a form‑error‑page tag‑ben megadott oldalt jeleníti meg. Ugyanezt egy saját űrlappal és egy mögötte lévő backing beannel megoldva megtarthatjuk a bejelentkezési kísérlet előtti oldal képét, kiegészítve azt a hibaüzenettel.

A fentiek ellenére bekerült a web.xml‑be a login‑form‑page és a form‑error‑page a szükséges security‑constraint tag‑ekkel együtt, hiszen így ha a felhasználó mégis védett erőforrást akarna elérni bejelentkezés nélkül (vagy a http session lejárta után), akkor sem hibaüzenettel fog találkozni, hanem a bejelentkező űrlappal.

A saját űrlap használatához ProgrammaticLogin-ra van szükség, ami egy kényelmes megoldás, viszont alkalmazásszerver-függő, így használatával elveszítjük az alkalmazás alkalmazásszerverek közti hordozhatóságát. A következőkben látni fogjuk, hogy ez nem jelent nagy problémát, hiszen például JBoss alatt is nagyon hasonló az API ([33]), csupán néhány sort kell módosítani a kódban, illetve az alkalmazáshoz csomagolt JAR fájlokat lecserélni.

Egy Glassfish alatti bejelentkezés és kijelentkezés elvégzéséhez a 22. ábrán látható kódsorokra van szükség.

import com.sun.appserv.security.ProgrammaticLogin;
...
ProgrammaticLogin programmaticLogin = new ProgrammaticLogin();
...
programmaticLogin.login("username", "password", "JDBCRealm",
	getRequest(), getResponse(), true);
...
programmaticLogin.logout(getRequest(), getResponse());

22. ábra: Bejelentkezés ProgrammaticLoginnal
Glassfish alkalmazásszerverre (részletek)

Látható, hogy a ProgrammaticLogin osztály login és logout metódusait kell meghívni, maga a ProgrammaticLogin osztály pedig a Glassfish lib/appserv-rt.jar fájljában található. Ezt fel kell venni a projekt által használt osztálykönyvtárak közé.

A login és logout metódusokból többféle áll rendelkezésre. Ha szervletből vagy managed beanből hívjuk, akkor olyat érdemes választani, aminek át lehet adni egy HttpServletRequest és HttpServletResponse objektumot is. A 22. ábrán is egy ilyen hívás látható. Így téve bejegyződik a munkamenetbe (http session) a felhasználó azonosítója, és a következő oldalon is bejelentkezve marad a kliens.

A szükséges HttpServletRequest és HttpServletResponse objektumok a 23. ábrán látható módon érhetőek el egy backing beanből.

FacesContext ctx = FacesContext.getCurrentInstance();
ExternalContext ectx = ctx.getExternalContext();
HttpServletRequest req = 
	(HttpServletRequest) ectx.getRequest();
HttpServletResponse resp = 
	(HttpServletResponse) ectx.getResponse();

23. ábra: HttpServletRequest és HttpServletResponse
objektumok elérése backing beanből

Sikeres bejelentkezés esetén a webkonténer továbbterjeszti az EJB-konténer felé a felhasználó adatait, amelyet a 24. ábrán szereplő kóddal lehet elérni az EJB-rétegben.

@Resource
SessionContext sessionContext;
...
String username =
	sessionContext.getCallerPrincipal().getName();

24. ábra: Bejelentkezett felhasználó adatainak elérése az EJB-rétegben

Ezen túl használhatóak még a javax.annotation.security csomag annotáció is az egyes metódusokhoz, osztályokhoz való hozzáférés vezérlésére (DeclareRoles, DenyAll, PermitAll, RolesAllowed, RunAs). Nem elégséges jogosultságok esetén javax.ejb.AccessLocalException dobódik („Client not authorized for this invocation.”).

Hozzászólások

JAAS

Szia

Glassfish v2.1-ben csináltam egy alkalmazást régebben. Kiválóan működött az authentikáció JAAS-al. Ldap címtárat használtam a user adatok tárolására. Java EE6-ban GFv3.0 mindent ugyanúgy csinálok és nem működik.
Nem hallottál valami változásról? Láttam, hogy Te is érdeklődsz a JAVA EE 6 felől.
Én csak egy változást találok (vagy csak nekem új, hogy nem csak csoportokat lehet felvinni a sun-web.xml-ben hanem usereket is).

Józsi

JAAS megoldva

A web.xml-ben a védett erőforrásokat nem lehet relatívan megadni hanem teljesen ki kell írni, hogy mondjuk
/faces/vedettoldalak/*
ekkor működik.

Örülök, hogy...

Szia,

Örülök, hogy megoldódott :) Köszi, hogy megírtad ide is!

üdv:
Miki

Tartalom átvétel