Magazine Java Authentication and Authorization Services Óbudai Egyetem, Java Enterprise Edition Műszaki Informatika szak Labor 11 Bedők Dávid 2016.10.05. v0.6
Java Authentication and Authorization Service Authentication can defined as the process to confirm the identity of an user. This can be achieved in a variety of ways, e.g. by entering a password, swiping an ID card, or using a biometrical scanner. The user need not be a human being, but can be a computer process. Authorization can be defined as the process of deciding whether an authenticated user/system is allowed to access a certain resource or perform a certain action or not. A system may have many logical sections/modules, and not all users might have access to all modules. This is where authorization comes into play. Though the user might have authenticated himself, he might not have sufficient authorization to access certain particular data items. JaaS provides a framework and an API for the authentication and authorization of users, whether they're human or automated processes. JaaS implements a Java version of the standard Pluggable Authentication Module (PAM) framework. 2
RedHat JBoss 3
Architecture LoginModules may prompt for and verify a user name and password. Others may read and verify a voice or fingerprint sample. 4
Realm A Realm is a "database" of usernames and passwords that identify valid users of a web application (or set of web applications), plus an enumeration of the list of roles associated with each valid user. A particular user can have any number of roles associated with their username. JDBCRealm - Accesses authentication information stored in a relational database, accessed via a JDBC driver. DataSourceRealm - Accesses authentication information stored in a relational database, accessed via a named JNDI JDBC DataSource. JNDIRealm - Accesses authentication information stored in an LDAP based directory server, accessed via a JNDI provider. MemoryRealm - Accesses authentication information stored in an in-memory object collection, which is initialized from an XML document. JAASRealm - Accesses authentication information through the Java Authentication & Authorization Service (JAAS) framework. 5
Mit kell tudnia egy ilyen framework-nek? Webalkalmazás és authentikáció kontextusában Az alkalmazásnak vannak public és vannak protected erőforrásai (weboldalai). A nyílvános elemeket bejelentkezés nélkül el lehet érni (ilyen alapértelmezés szerint a login oldal, de más erőforrások is lehetnek (pl. képek, stílus lapok, vagy akár nem szenzitív adatot tartalmazó lapok), míg a védett elemeket csak sikeres authentikációt követően. Ha egy védett weboldalt meglátogatunk, akkor a framework megnézi authentikálva vagyunk-e, és ha nem, átdob minket a bejelentkező képernyőre (automatikusan). Sikeres bejelentkezést követően az eredetileg meglátogatni kívánt oldalra irányít minket (ez az ún. landing page). 6
Mit kell tudnia egy ilyen framework-nek? Webalkalmazás és authorizáció kontextusában Bejelentkezést követően bizonyos műveletek csak bizonyos szerepkörű felhasználók számára érhető el. E védett műveleteket szerepkörökhöz rendeljük, és csak akkor jelennek meg/érhetőek el, ha a bejelentkezett felhasználó a megadott szerepkör birtokában van (authorizáció). Magukat a védett erőforrásokat is köthetjük egy konkrét szerepkörhöz (ez általában egy általános szerepkör, mellyel a legtöbb felhasználó rendelkezik, de pl. egy Admin felületet csak az adminok számára teszünk elérhetővé). Egy elérhető erőforráson belül bizonyos műveleteket teszünk jogosultság/szerepkör függvényében elérhetővé. 7
Basic JaaS és JBoss Nem kell saját LoginModule-t készítenünk, választhatunk előre elkészítettek közül, melyeket paraméterek segítségével igényeinkre szabunk. Cél: PostgreSQL-ben tárolt felhasználók/jelszavak/szerepkörök és összerendeléseik használata Konfiguráció: lekérdezések beállítása JBoss számára, melyeket automatikusan használjon authentikáció és authorizáció során Saját webes bejelentkezés készítése (xhtml form based) Védett erőforrások (bejelentkezéshez kötött) és védett műveletek (szerepkörhöz kötött) definiálása 8
PostgreSQL lekérdezések naplózása Mivel a lekérdezeket automatikusan a JBoss fogja végrehajtani, fejlesztési szempontból nagyon hasznos ha ezen automatizmus másik oldalán tudjuk naplózni az így végrehajtott lekérdezéseket. Napló file: [PG-HOME]\data\pg_log\postgresql-[YYYY-MM-DD]_[random].log Konfigurációs file: [PG-HOME]\data\postgresql.conf log_statement = 'all' postgresql.conf # none, ddl, mod, all Restart postgresql: Windows service-ek között megtalálható (Stop/Start) > [PG-HOME]/bin/pg_ctl -D [PG-HOME]/data/ restart PG-HOME: c:\program Files\PostgreSQL\[version] (windows) /Library/PostgreSQL/[version] (mac os) 9
Feladat Magazinok CRUD művelete köré épített webalkalmazás (a BookStore alkalmazás mintájára). A stílus lapok (css) elérhetőek bárki számára A lekérdező műveletek sikeres bejelentkezés után érhetőek el A módosító műveletek (új magazin, szerkesztés, törlés) kizárólag az magadmin szerepkörrel rendelkező felhasználók számára érhető el, minden más művelet a maguser szerepkörrel elvégezhető (lekérdezések) GIT \jboss\magazine 10
Adatbázis oldal Táblák CREATE TABLE magazinecategory (..) CREATE TABLE magazine (..) CREATE TABLE appuser ( appuser_id SERIAL NOT NULL, appuser_name CHARACTER VARYING(100) NOT NULL, appuser_password CHARACTER VARYING(100) NOT NULL, CONSTRAINT PK_APPUSER_ID PRIMARY KEY (appuser_id) ); CREATE TABLE role ( role_id SERIAL NOT NULL, role_name CHARACTER VARYING(100) NOT NULL, CONSTRAINT PK_ROLE_ID PRIMARY KEY (role_id) ); CREATE TABLE userrole ( userrole_id SERIAL NOT NULL, userrole_appuser_id INTEGER NOT NULL, userrole_role_id INTEGER NOT NULL, CONSTRAINT PK_USERROLE_ID PRIMARY KEY (userrole_id), CONSTRAINT FK_USERROLE_USER FOREIGN KEY (userrole_appuser_id) create-schema.sql plaintext jelszó Egy felhasználó tetszőleges szerepkör birtokában lehet. REFERENCES appuser (appuser_id) MATCH SIMPLE ON UPDATE RESTRICT ON DELETE RESTRICT, CONSTRAINT FK_USERROLE_ROLE FOREIGN KEY (userrole_role_id) REFERENCES role (role_id) MATCH SIMPLE ON UPDATE RESTRICT ON DELETE RESTRICT 11
Adatbázis oldal Kezdeti adatok INSERT INTO role (role_id, role_name) VALUES (0, 'maguser'); INSERT INTO role (role_id, role_name) VALUES (1, 'magadmin'); initial-data.sql SELECT SETVAL('role_role_id_seq', COALESCE(MAX(role_id), 1) ) FROM role; INSERT INTO appuser (appuser_id, appuser_name, appuser_password) VALUES (0, 'alice', 'a123'); INSERT INTO appuser (appuser_id, appuser_name, appuser_password) VALUES (1, 'bob', 'b123'); INSERT INTO appuser (appuser_id, appuser_name, appuser_password) VALUES (2, 'charlie', 'c123'); SELECT SETVAL('appuser_appuser_id_seq', COALESCE(MAX(appuser_id), 1) ) FROM appuser; INSERT INTO userrole (userrole_appuser_id, userrole_role_id) VALUES (0, 0); INSERT INTO userrole (userrole_appuser_id, userrole_role_id) VALUES (0, 1); INSERT INTO userrole (userrole_appuser_id, userrole_role_id) VALUES (1, 0); INSERT INTO userrole (userrole_appuser_id, userrole_role_id) VALUES (2, 0); Mindhárom felhasználó rendelkezik a maguser szerepkörrel, alice azonban e mellett a magadmin szerepkör birtokában is van. 12
JBoss konfiguráció Datasource <subsystem xmlns="urn:jboss:domain:datasources:1.2"> <datasources> <datasource jndi-name=" java:jboss/datasources/magazineds" pool-name="magazinedspool" enabled="true" use-java-context="true"> <connection-url> jdbc:postgresql://localhost:5432/magazinedb</connection-url> <driver>postgresql</driver> <security> <user-name>magazine_user</user-name> <password>123topsecret321</password> </security> <validation> <check-valid-connection-sql>select 1</check-valid-connection-sql> <validate-on-match>true</validate-on-match> <background-validation>false</background-validation> </validation> <statement> <share-prepared-statements>false</share-prepared-statements> </statement> </datasource> </datasources> </subsystem> standalone.xml Ebben semmi újdonság nincs a korábbiakhoz képest. 13
JBoss konfiguráció Security-Domain és LoginModule <subsystem xmlns="urn:jboss:domain:security:1.2"> <security-domains> <security-domain name=" mag-security-db-domain"> <authentication> <login-module code=" Database" flag="required"> <module-option name=" dsjndiname" value="java:jboss/datasources/magazineds"/> <module-option name=" principalsquery" value="select appuser_password FROM appuser WHERE appuser_name =?"/> <module-option name=" rolesquery" value="select role_name, 'Roles' FROM userrole INNER JOIN appuser ON (appuser_id = userrole_appuser_id) INNER JOIN role ON (role_id = userrole_role_id) WHERE appuser_name =?"/> </login-module> </authentication> </security-domain> </security-domains> </subsystem> standalone.xml Datasource JNDI neve! A Security-Domain JNDI neve java:/jaas/ mag-security-db-domain lesz. A LoginModule code mezőnek konstansa mögött (Database) egy osztály van, mely megadása ugyanolyan jó (pl. UserRoles esetén org.jboss.security.auth.spi.usersrolesloginmodule, Database esetén pedig org.jboss.security.auth.spi.databaseserverloginmodule. 14
Control Flag Multiple Login Module! <login-module code="..." flag=" required">...</login-module> required: The login module is required to succeed for the authentication to be successful. If any required module fails, the authentication will fail. The remaining login modules in the stack will be called regardless of the outcome of the authentication. requisite: The login module is required to succeed. If it succeeds, authentication continues down the login stack. If it fails, control immediately returns to the application. sufficient: The login module is not required to succeed. If it does succeed, control immediately returns to the application. If it fails, authentication continues down the login stack. optional: The login module is not required to succeed. Authentication still continues to proceed down the login stack regardless of whether the login module succeeds or fails. Pl.: Ha különféle képpen is be lehet lépni az alkalmazásba (de mindegyik elégséges), akkor két sufficient login module-t kell felvinni a security-domain alá. 15
SQL Konfiguráció principalsquery SELECT appuser_password FROM appuser WHERE appuser_name =? The prepared statement query equivalent to: select Password from Principals where PrincipalID=?. If not specified this is the exact prepared statement that will be used. SELECT role_name, 'Roles' FROM userrole INNER JOIN appuser ON rolesquery Value of RoleGroup column always has to be Roles (with capital 'R'). This is specific to JBoss. (appuser_id = userrole_appuser_id) INNER JOIN role ON (role_id = userrole_role_id) WHERE appuser_name =? The prepared statement query equivalent to: select Role, RoleGroup from Roles where PrincipalID=?. If not specified this is the exact prepared statement that will be used. 16
JBoss konfiguráció Realm és Naplózás <management> <security-realms> <security-realm name=" mag-realm"> <authentication> <jaas name=" mag-security-db-domain"/> </authentication> </security-realm> </security-realms> </management>... <profile>... <subsystem xmlns="urn:jboss:domain:logging:1.5">... <logger category=" org.jboss.security"> <level name=" TRACE"/> </logger>... </subsystem> </profile> Security-Domain neve! standalone.xml A folyamattal kapcsolatos történesek naplózása (nem általunk implementált kód). 17
Webalkalmazás felkészítése Login oldal készítése Űrlap egy név és egy jelszó mezővel LoginError oldal készítése Sikertelen bejelentkezést követően ez töltődik be Általában visszadobjuk a Login oldalra egy hibaüzenet kíséretében (vagy a megjelenő oldalról link segítségével lehet a Login oldalt ismét betölteni) Logout oldal készítése A bejelentkezett felhasználó kiléptetése a rendszerből. Általában cél a Login page-ra való visszadobás sikeres kijelentkeztetés esetén Error oldal(ak) készítése Minden egyéb Security hiba során betöltődő oldal(ak). 18
Login page (servlet side) LoginServlet.java @WebServlet(" /Login") public class LoginServlet extends HttpServlet implements LoginAttribute { @Override protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { request.setattribute(attr_username, ""); request.setattribute(attr_error, ""); final RequestDispatcher view = request.getrequestdispatcher( "login.jsp"); view.forward(request, response); } } Az ATTR_USERNAME és az ATTR_ERROR attribútumokban a Login page-en beírt felhasználó név, és az esetleges hibaüzenet szövegét tároljuk. A login.jsp dolgozza fel őket, hibás authentikáció esetén fogjuk tölteni az értéküket. 19
Login page (jsp side).. <link rel="stylesheet" type="text/css" href=" style/page.css" />.. <% String username = (String) request.getattribute(loginattribute.attr_username); String errormessage = (String) request.getattribute(loginattribute.attr_error); %> <form action=" j_security_check" method="post"> <legend>login</legend> <div class="error"><%= errormessage %></div> <label for="username">username: </label> <input type="text" name=" j_username" id="username" value="<%= username >" /> <label for="password">password: </label> <input type="password" name=" j_password" id="password" /> <input type="submit" name="submit" value="login" /> </form>.. Ha van hibaüzenet (errormessage ), illetve már korábban beírt felhasználónév (username), akkor ezeket megjelenítjük a login oldalon (hibás authentikáció utáni újratöltés esete lesz). login.jsp Public resource! A j_* elnevezések (servlet url/action és az űrlap felhasználónév és jelszó mezőjének nevei) az API által előírtak, ebben a formában kell őket alkalmazni. 20
LoginError page (servlet side) LoginErrorServlet.java @WebServlet(" /LoginError") public class LoginErrorServlet extends HttpServlet implements LoginAttribute { @Override protected void dopost(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { final String username = request.getparameter(" j_username"); request.setattribute(attr_username, username); request.setattribute(attr_error, " Login failed"); Hibaüzenet } final RequestDispatcher view = request.getrequestdispatcher( "login.jsp"); view.forward(request, response); } Hiba esetén a j_security_check servlet átdobja a kérést a loginerror page-re. A kérésből kikérhetük az űrlap mezőit (jelen esetben a nevet kikérjük, hogy át tudjuk adni a login.jsp-nek). 21
Logout page (servlet side) @WebServlet(" /Logout") public class LogoutServlet extends HttpServlet { LogoutServlet.java @Override protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { response.setheader("cache-control", "no-cache, no-store"); response.setheader("pragma", "no-cache"); response.setheader("expires", new java.util.date().tostring()); if (request.getsession( false)!= null) { request.getsession( false).invalidate(); } } } if (request.getsession()!= null) { request.getsession().invalidate(); } request.logout(); response.sendredirect(page.list.geturl()); Az itt leírt megoldás egyfajta best practice. A Redirect a servlet végén bármely védett oldalra mutathat. Ha sikeres volt a kijelentkeztetése a felhasználónak, a védett URL betöltése ki fogja váltani a Login page betöltését. 22
Error page @WebServlet(" /Error") public class ErrorServlet extends HttpServlet { ErrorServlet.java @Override protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException { final RequestDispatcher view = request.getrequestdispatcher( "error.jsp"); view.forward(request, response); } Security-vel kapcsolatos hibák esetén definiálhatóak Error } page-ek (akár több is), melyek pl. HTTP hibakódokhoz lesznek köthetőek. <%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8" %>.. <meta http-equiv="content-type" content="text/html; charset=utf-8"> <link rel="stylesheet" type="text/css" href="style/page.css" /> <title>:: Error ::</title> </head> <body>error</body> </html> error.jsp 23
Webalkalmazás konfiguráció Védett erőforrások <web-app...> <security-constraint> <display-name>magazine protected security constraint</display-name> <web-resource-collection> <web-resource-name>protected Area</web-resource-name> <url-pattern> /*</url-pattern> <http-method>get</http-method> <http-method>post</http-method> <http-method>put</http-method> <http-method>delete</http-method> <http-method>head</http-method> <http-method>options</http-method> <http-method>trace</http-method> </web-resource-collection> <auth-constraint> <role-name> maguser</role-name> <role-name> magadmin</role-name> </auth-constraint> <user-data-constraint> <transport-guarantee>none</transport-guarantee> </user-data-constraint> </security-constraint> </web-app> WEB-INF/web.xml Minden oldal (minden HTTP method esetén) védett területen van (kivéve majd az, melyet nyitottá teszünk). Az oldalak maguser vagy magadmin szerepkör birtokában érhetőek el. Az adatbázisban is szerepelnek ezek a szerepkörök. 24
Webalkalmazás konfiguráció Nyilvános erőforrások <web-app...>... <security-constraint> <display-name>magazine public security constraint</display-name> <web-resource-collection> <web-resource-name>public</web-resource-name> <url-pattern> /style/*</url-pattern> <url-pattern> /Logout</url-pattern> <http-method>get</http-method> </web-resource-collection> </security-constraint>... </web-app> WEB-INF/web.xml A stílus lapok lekérése és a kijelentkező servlet elérhető bejelentkezés nélkül is. A Login page alapértelmezés szerint elérhető, viszont az általa hivatkozott stílus lapot már nyitottá kell tenni. 25
Webalkalmazás konfiguráció Login config és Security roles <web-app...> <login-config> <auth-method> FORM</auth-method> <form-login-config> <form-login-page> /Login</form-login-page> <form-error-page> /LoginError</form-error-page> </form-login-config> </login-config> <security-role> <description>generic user</description> <role-name> maguser</role-name> </security-role> <security-role> <description>administrator</description> <role-name> magadmin</role-name> </security-role> <error-page> <error-code>403</error-code> <location>/error</location> </error-page> </web-app> WEB-INF/web.xml Az authentikáció formája többféle lehet. Saját űrlap készítése esetén (leggyakoribb) a FORM a helyes érték, de lehet még BASIC, DIGEST és CLIENT-CERT is. Az űrlap authentikáció konfigja a Login page (form-login-page ) és a LoginError page (form-error-page ) megadásából áll. Ide a servlet url pattern-jét kell megadni (JSP esetén ez a JSP neve). Az elérhető szerepköröket is fel kell sorolni a security-role element segítségével. HTTP 403-mas (Forbidden) status code esetén megadott hibaoldal. 26
Webalkalmazás konfiguráció Auth methods <web-app...>... <login-config> <auth-method> BASIC</auth-method> <realm-name> mag-realm</realm-name> JBoss kapcsolat Realm! </login-config>... </web-app> BASIC authentikáció: böngésző beépített login ablakot dob fel (~javascript), melyen a felhasználónév és a jelszó megadható BASIC auth method esetén megadható a realm neve a web.xml-ben, azonban jboss esetén ekkor is használható a jboss-web.xml, ahol a Security Domain JNDI nevének a megadása szükséges WEB-INF/web.xml Figyelem! Ez a web.xml minta NEM a Magazine project-hez tartozik. 27
Webalkalmazás konfiguráció JBoss specifikus konfiguráció WEB-INF/jboss-web.xml <?xml version="1.0" encoding="utf-8"?> <jboss-web> <security-domain>java:/jaas/mag-security-db-domain</security-domain> </jboss-web> A JBoss standalone.xml -ben beállított security-domain JNDI neve. 28
Webalkalmazás és JBoss konfigurációk kapcsolata Webalkalmazás leírója (web.xml) hivatkozhat a JBoss standalone.xml mag-realm nevű security-realm-re*. A security-realm hivatkozik a mag-security-db-domain nevű security-domain-re (standalone.xml-en belül). A webalkalmazás JBoss specifikus leírója (jboss-web.xml) közvetlenül is hivatkozik a JBoss standalone.xml mag-security-db-domain nevű security-domain nevére (JNDI név alapján) (ez egyébként szükséges és elégséges konfiguráció JBoss esetén). A mag-security-db-domain tartalmazza a Database login module konfigurációját, melyen keresztül a fizikai adatbázis (DataSource JNDI neve) és az azon végrehajtandó natív lekérdezések is elérhetőek. * BASIC auth method esetén 29
Webalkalmazás authorizáció Role-Based Access Control *Servlet.java @Override protected void doget(httpservletrequest request, HttpServletResponse response) throws ServletException, IOException {... if ( request.isuserinrole(" magadmin") ) {... }... } list.jsp <% if (request.isuserinrole(" magadmin")) { %> <div> <a href="magazine?reference=-1&edit=1">create</a> a brand new magazine. </div> <% } %> 30
EJB module konfiguráció mag-ejbservice project <?xml version="1.0" encoding="utf-8"?> <jboss:ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:jboss="http://www.jboss.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xmlns:s="urn:security:1.1" version="3.1" impl-version="2.0"> META-INF/jboss-ejb3.xml <assembly-descriptor> <s:security> <ejb-name>*</ejb-name> <s:security-domain> mag-security-db-domain</s:security-domain> </s:security> </assembly-descriptor> </jboss:ejb-jar> Ha minden jogosultság ellenőrzés nélkül minden EJB metódus hívható, akkor nincs szükség a konfigurációra! Hasonlóan a Webalkalmazás jboss-web.xml leírójához, ha az EJB module projektekben is szeretnék Role-Based Access Control-t (RBAC) használni, akkor meg kell adnunk a security-domain nevét a jboss-ejb3.xml leíróban (ebben a file-ban nem a JNDI név kell). 31
EJB module authorizáció Role-Based Access Control @PermitAll @Stateless(mappedName = "ejb/magazinefacade") public class MagazineFacadeImpl implements MagazineFacade {... MagazineFacadeImpl.java } @Override @RolesAllowed(" magadmin") public void removemagazine( final String reference) throws FacadeException { try { this.service.delete(reference); } catch (final PersistenceServiceException e) { LOGGER.error(e, e); throw new FacadeException(e.getLocalizedMessage()); } } @PermitAll: minden szerepkör számára elérhető Ha konfigurálva van a security-domain, akkor alapértelmezés szerint egyik metódus sem hívható meg, vagyis muszáj a jogosultságot megadni (ezt lehet xml szinten is). @RolesAllowed(" magadmin") vagy @RolesAllowed({ " magadmin", "maguser" }): a megadott vagy felsorolt szerepkörök számára elérhető Osztály szinten: minden metódusra érvényes 32
Oracle WebLogic 33
Azonos koncepció, apró különbségek dd*: deployment descriptor JBoss WebLogic web module container specifikus dd* ejb module container specifikus dd* security role nevére nézett ismert limitációk security role security realm-ekre nézett ismert limitációk elnevezésbeli különbség hivatkozás alkalmazásból weblogic-ejb-jar.xml jboss-ejb3.xml az application role megegyezik a security role-lal Tetszőleges számú security realm is létezhet egyidőben. Login Module with Control Flag a Security Domain JNDI vagy rövid nevére weblogic.xml jboss-web.xml Kötőjelek (hyphens) használata esetén az Admin Console-ról nem kezelhető az application role logikailag szétválik a security role-tól Több lehet, de kizárólag egy lehet aktív (az inaktív semmire sem használható! Authentication Provider with Control Flag Nincs hivatkozás Security Realm-re (kizárólag az egyetlen aktív használható). 34
Application Role vs. Security Role Az Application Role logikailag szétválik a Security Role-tól Pl. egy Application Role-hoz egy vagy több User, vagy egy vagy több Security Role tartozhat. Az összerendelés megadása azonban kötelező a container specifikus deployment descriptorban (különben nem lesz kapcsolat a Security Realm-el). <security-role-assignment> <role-name>abc</role-name> <principal-name>xyz</principal-name> <principal-name>etc</principal-name> </security-role-assignment> ABC: Application Role (web.xml-ben és Java kódban használt szerepkör. XYZ és ETC: Security Role (ajánlott) vagy Security User neve, mely a Security Realm-ben van konfigurálva. WEB-INF/weblogic.xml <weblogic-web-app...> <security-role-assignment>... </security-role-assignment> <security-role-assignment>... </security-role-assignment> </weblogic-web-app> web module META-INF/weblogic-ejb-jar.xml <weblogic-ejb-jar...> <security-role-assignment>... </security-role-assignment> <security-role-assignment>... </security-role-assignment> </weblogic-ejb-jar> ejb module 35
Logine Module vs. Authentication Provider Logine Module JBoss Több Login Module létezhet egy Security Domain alatt. A Security Realm kötődhet egy Security Domain-hez (és visszafelé is igaz ez). A Security Realm leginkább remote elérés esetén használatos. Authentication Provider WebLogic Több Authentication Provider létezhet egy Security Realm alatt. Security Domain elnevezés nem jelenik meg WebLogic esetén. Az alapértelmezett myrealm Security Realm-hez fogunk tudni felvenni egy olyan Authentication Provider-t, mely saját adatbázis alapján authentikál. Ezt, és az eredetileg is itt lévő DefaultAuthenticator Control Flag-jét átállítjuk SUFFICIENT-re (eredetileg REQUIRED). 36
DataSource konfigurálása WebLogic Server Administration Console Services Data Sources Configuration tab New Generic Data Source Name: magazineds JNDI name: jdbc/datasource/magazineds Target: myserver Database type: PostgreSQL Next, Next.. Database name: magazinedb Host name: localhost Port: 5432 (default) Database user name: magazine_user Password: 123topSECret321 Ismétlés.. 37
Security Realm konfigurálása WebLogic Server Administration Console Security Realms myrealm kiválasztása Providers tab New Name: magazineauthenticator Type: SQLAuthenticator magazineauthenticator kiválasztása Configuration tab Common tab Control Flag: SUFFICIENT Save Configuration tab Provider Specific tab Plaintext Passwords Enabled (checked) Data Source Name: magazineds Password Style Retained (checked) Descriptions Supported (unchecked) SQL Queries (folyt. köv) 38
SQL Queries I. SQL Get Users Password (JBoss: principalsquery) SELECT appuser_password FROM appuser WHERE appuser_name =? SQL Set User Password UPDATE appuser SET appuser_password =? WHERE appuser_name =? SQL User Exists SELECT appuser_name FROM appuser WHERE appuser_name =? SQL List Users SELECT appuser_name FROM appuser WHERE appuser_name LIKE? SQL Create User INSERT INTO appuser (appuser_id, appuser_name, appuser_password) VALUES (?,?,?) SQL Remove User DELETE FROM appuser WHERE appuser_name =? SQL List Groups SELECT role_name FROM role WHERE role_name LIKE? SQL Group Exists SELECT role_name FROM role WHERE role_name =? SQL Create Group INSERT INTO role (role_id, role_name) VALUES (?,?) SQL Remove Group DELETE FROM role WHERE role_name =? SQL Is Member SELECT appuser_name FROM userrole INNER JOIN appuser ON ( appuser_id = userrole_appuser_id ) INNER JOIN role ON ( role_id = userrole_role_id ) WHERE appuser_name =? AND role_name =? 39
SQL Queries II. SQL List Member Groups (JBoss: rolesquery, RoleGroup nélkül) SQL List Group Members SQL Remove Group Memberships SQL Add Member To Group SQL Remove Member From Group SQL Remove Group Member SELECT role_name FROM userrole INNER JOIN appuser ON ( appuser_id = userrole_appuser_id ) INNER JOIN role ON ( role_id = userrole_role_id ) WHERE appuser_name =? SELECT appuser_name FROM userrole INNER JOIN appuser ON ( appuser_id = userrole_appuser_id ) INNER JOIN role ON ( role_id = userrole_role_id ) WHERE appuser_name LIKE? AND role_name =? DELETE FROM userrole WHERE userrole_role_id = ( SELECT role_id FROM role WHERE role_name =? ) AND userrole_appuser_id = ( SELECT appuser_id FROM appuser WHERE appuser_name =? ) INSERT INTO userrole (userrole_appuser_id, userrole_role_id) VALUES (?,?) DELETE FROM userrole WHERE userrole_role_id = ( SELECT role_id FROM role WHERE role_name =? ) AND userrole_appuser_id = ( SELECT appuser_id FROM appuser WHERE appuser_name =? ) DELETE FROM userrole WHERE userrole_role_id = ( SELECT role_id FROM role WHERE role_name =? ) Description specifikus lekérdezések Kikapcsoltuk a description használatát.. 40
Alice sikeres bejelentkezése SELECT appuser_password FROM appuser WHERE appuser_name = 'alice'; SELECT role_name FROM userrole INNER JOIN appuser ON ( appuser_id = userrole_appuser_id ) INNER JOIN role ON ( role_id = userrole_role_id ) WHERE appuser_name = 'alice'; SELECT role_name FROM userrole INNER JOIN appuser ON ( appuser_id = userrole_appuser_id ) INNER JOIN role ON ( role_id = userrole_role_id ) WHERE appuser_name = 'maguser'; SELECT role_name Lefut a principal name-ekre nézve is (weblogic.xml), lévén ezek lehetnek Security Role-ok és User-ek is! FROM userrole INNER JOIN appuser ON ( appuser_id = userrole_appuser_id ) INNER JOIN role ON ( role_id = userrole_role_id ) WHERE appuser_name = 'magadmin'; 41
Security Realm ellenőrzése Server restart WebLogic Server Administration Console Security Realms myrealm kiválasztása Users and Groups tab Users tab Name Provider Groups tab alice bob charlie weblogic magazineauthenticator magazineauthenticator magazineauthenticator DefaultAuthenticator Name Provider oeadmin magazineauthenticator oeuser magazineauthenticator... DefaultAuthenticator alice kiválasztása után a Groups tabon láthatóvá válnak a Security Role összerendelései is, miszerint oeadmin és oeuser szerepkörökkel rendelkezik 42
Magazine project módosításai Log4j lecserélése Java Logging-ra Hibernate dependency lecserélése Eclipselink-re Logout Servlet-ben a request.logout() kitörlése NullPointerException-t dob (ismert hiba) mag-user és mag-admin Application Role-ok használata maguser és magadmin helyett list.jsp magazine.jsp MagazineFacadeImpl jboss-web.xml helyett weblogic.xml jboss-ejb3.xml helyett weblogic-ejb-jar.xml *.jsp <% if (request.isuserinrole("mag-admin")) { %>... <% } %> *.java @RolesAllowed("mag-admin") public void removemagazine(...)... {... } 43
Web module konfiguráció mag-weblayer project WEB-INF/web.xml <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">... <security-constraint> <display-name>magazine protected security constraint</display-name>... <auth-constraint> <role-name>mag-user</role-name> <role-name>mag-admin</role-name> Application Role </auth-constraint>... </security-constraint>... <security-role> <description>generic user</description> <role-name>mag-user</role-name> </security-role> <security-role> <description>administrator</description> <role-name>mag-admin</role-name> </security-role>... </web-app> 44
Web module konfiguráció mag-weblayer project <?xml version='1.0' encoding='utf-8'?> <weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance"> <security-role-assignment> <role-name> mag-user</role-name> <principal-name> maguser</principal-name> </security-role-assignment> <security-role-assignment> <role-name> mag-admin</role-name> <principal-name> magadmin</principal-name> </security-role-assignment> </weblogic-web-app> WEB-INF/weblogic.xml Application Role: mag-user és mag-admin Security Role: maguser és magadmin (ezek vannak adatbázisban) 45
EJB module konfiguráció mag-ejbservice project <?xml version="1.0" encoding="utf-8"?> <weblogic-ejb-jar xmlns="http://www.bea.com/ns/weblogic/90" xmlns:j2ee="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/xmlschema-instance" xsi:schemalocation="http://www.bea.com/ns/weblogic/90 http://www.bea.com/ns/weblogic/90/weblogic-ejb-jar.xsd"> <security-role-assignment> <role-name> mag-user</role-name> <principal-name> maguser</principal-name> </security-role-assignment> <security-role-assignment> <role-name> mag-admin</role-name> <principal-name> magadmin</principal-name> </security-role-assignment> META-INF/weblogic-ejb-jar.xml </weblogic-ejb-jar> Kizárólag a root tag-ben tér el a weblogic.xml-től. 46