Jakarta EE 8 Security API

1. Áttekintés

A Jakarta EE 8 Security API az új szabvány és egy hordozható módszer a Java-tárolók biztonsági aggályainak kezelésére.

Ebben a cikkben, megvizsgáljuk az API három alapvető tulajdonságát:

  1. HTTP hitelesítési mechanizmus
  2. Identity Store
  3. Biztonsági kontextus

Először megértjük, hogyan kell konfigurálni a megadott megvalósításokat, majd hogyan kell egy egyedi megvalósítani.

2. Maven-függőségek

A Jakarta EE 8 Security API beállításához vagy szerver által biztosított, vagy kifejezetten megvalósított megvalósításra van szükség.

2.1. A kiszolgáló megvalósításának használata

A Jakarta EE 8 kompatibilis szerverek már biztosítják a Jakarta EE 8 Security API megvalósítását, és ezért csak a Jakarta EE Web Profile API Maven artefaktumra van szükségünk:

  javax javaee-web-api 8.0 biztosított 

2.2. Kifejezett megvalósítás használata

Először meghatározzuk a Jakarta EE 8 Security API Maven-műtárgyát:

  javax.security.enterprise javax.security.enterprise-api 1.0 

Ezután hozzáadunk egy megvalósítást, például a Soteria-t - a referencia-megvalósítást:

  org.glassfish.soteria javax.security.enterprise 1.0 

3. HTTP hitelesítési mechanizmus

Jakarta EE 8 előtt deklaratív módon konfiguráltuk a hitelesítési mechanizmusokat a web.xml fájl.

Ebben a verzióban a Jakarta EE 8 Security API tervezte az újat HttpAuthenticationMechanism interfész helyett. Ezért a webalkalmazások már konfigurálhatják a hitelesítési mechanizmusokat azáltal, hogy biztosítják ennek az interfésznek a megvalósítását.

Szerencsére a tároló már biztosítja a Servlet-specifikáció által meghatározott három hitelesítési módszer mindegyikének megvalósítását: Alap HTTP-hitelesítés, űrlapalapú hitelesítés és egyedi űrlapalapú hitelesítés.

Ezenkívül megjegyzéssel látja el az egyes megvalósításokat:

  1. @BasicAuthenticationMechanismDefinition
  2. @FormAuthenticationMechanismDefinition
  3. @CustomFormAuthenrticationMechanismDefinition

3.1. Alapvető HTTP-hitelesítés

Mint fent említettük, egy webalkalmazás csak a. Használatával konfigurálhatja az alapvető HTTP-hitelesítést @BasicAuthenticationMechanismDefinition annotáció egy CDI-babon:

@BasicAuthenticationMechanismDefinition (realmName = "userRealm") @ApplicationScoped public class AppConfig {}

Ezen a ponton a Servlet-tároló keresi és példányosítja a HttpAuthenticationMechanism felület.

A jogosulatlan kérelem beérkezését követően a tároló megkérdi az ügyfelet, hogy adjon meg megfelelő hitelesítési információkat a WWW-hitelesítés válasz fejléc.

WWW-hitelesítés: Basic realm = "userRealm"

Ezután az ügyfél elküldi a felhasználónevet és jelszót kettősponttal elválasztva:: és a Base64-be kódolva Engedélyezés kérés fejléc:

// user = baeldung, password = baeldung Engedélyezés: Basic YmFlbGR1bmc6YmFlbGR1bmc = 

Vegye figyelembe, hogy a hitelesítő adatok megadásához bemutatott párbeszédpanel a böngészőből származik, és nem a szerverről.

3.2. Formalapú HTTP-hitelesítés

A @FormAuthenticationMechanismDefinition az annotáció űrlap alapú hitelesítést vált ki a Servlet specifikáció szerint.

Ezután lehetőségünk van megadni a bejelentkezési és hibaoldalakat, vagy az alapértelmezett ésszerű oldalakat használni /Belépés és /bejelentkezési hiba:

@FormAuthenticationMechanismDefinition (loginToContinue = @LoginToContinue (loginPage = "/login.html", errorPage = "/login-error.html")) @ApplicationScoped public class AppConfig {}

A hivatkozás eredményeként bejelentkezési oldal, a kiszolgálónak el kell küldenie az űrlapot az ügyfélnek:

Ezután az ügyfélnek el kell küldenie az űrlapot egy előre meghatározott háttér-hitelesítési folyamathoz, amelyet a tároló biztosít.

3.3. Egyéni űrlap alapú HTTP-hitelesítés

Egy webalkalmazás a kommentár használatával kiválthatja az egyéni űrlap alapú hitelesítés megvalósítását @CustomFormAuthenticationMechanismDefinition:

@CustomFormAuthenticationMechanismDefinition (loginToContinue = @LoginToContinue (loginPage = "/login.xhtml")) @ApplicationScoped public class AppConfig {}

De az alapértelmezett űrlapalapú hitelesítéstől eltérően konfigurálunk egy egyéni bejelentkezési oldalt, és meghívjuk a SecurityContext.authenticate () módszer mint háttérhitelesítési folyamat.

Vessünk egy pillantást a hátlapra LoginBean valamint a bejelentkezési logikát:

@Named @RequestScoped public class LoginBean {@Inject private SecurityContext securityContext; @NotNull private String felhasználónév; @NotNull private String jelszó; public void login () {Credential credential = new UsernamePasswordCredential (felhasználónév, új jelszó (jelszó)); AuthenticationStatus status = securityContext .authenticate (getHttpRequestFromFacesContext (), getHttpResponseFromFacesContext (), withParams (). Hitelesítő adatok (hitelesítő adatok)); // ...} // ...}

A szokás hivatkozásának eredményeként login.xhtml oldalon az ügyfél elküldi a kapott űrlapot a LoginBean 's Belépés() módszer:

//... 

3.4. Egyéni hitelesítési mechanizmus

A HttpAuthenticationMechanism interfész három módszert határoz meg. A legfontosabb az validateRequest () amelynek megvalósítását biztosítanunk kell.

A másik két módszer alapértelmezett viselkedése, secureResponse () és cleanSubject (), elegendő a legtöbb esetben.

Nézzünk meg egy megvalósítási példát:

@ApplicationScoped public class CustomAuthentication végrehajtja a HttpAuthenticationMechanism {@Orride public AuthenticationStatus validateRequest (HttpServletRequest kérés, HttpServletResponse válasz, HttpMessageContext httpMsgContext) dobja AuthenticationPlay felhasználónév Karakterlánc jelszó = response.getParameter ("jelszó"); // a UserDetail gúnyolódása, de a való életben megszerezhetjük egy adatbázisból UserDetail userDetail = findByUserNameAndPassword (felhasználónév, jelszó); if (userDetail! = null) {return httpMsgContext.notifyContainerAboutLogin (új CustomPrincipal (userDetail), új HashSet (userDetail.getRoles ())); } return httpMsgContext.responseUnauthorized (); } // ...}

Itt a megvalósítás biztosítja az érvényesítési folyamat üzleti logikáját, de a gyakorlatban ajánlott a IdentityStore keresztül IdentityStoreHandler by hivatkozva érvényesít.

A megvalósítást a @ApplicationScoped annotáció, mivel CDI-kompatibilisnek kell lennie.

A hitelesítő adatok érvényes ellenőrzése és a felhasználói szerepek esetleges visszakeresése után a megvalósításnak akkor értesítenie kell a konténert:

HttpMessageContext.notifyContainerAboutLogin (Fő megbízó, Csoportok beállítása)

3.5. A Servlet Security kikényszerítése

Egy webes alkalmazás kikényszerítheti a biztonsági korlátozásokat a @ használatávalServletSecurity a Servlet-megvalósítás kommentárja:

@WebServlet ("/ secured") @ServletSecurity (érték = @HttpConstraint (roleAllowed = {"admin_role"}), httpMethodConstraints = {@HttpMethodConstraint (value = "GET", szerepekAllowed = {"user_role"}), @Httpint = "POST", szerepekAllowed = {"admin_role"})}}) A SecuredServlet nyilvános osztály kiterjeszti a HttpServletet {}

Ennek a kommentárnak két attribútuma van - httpMethodConstraints és érték; httpMethodConstraints egy vagy több megkötés megadására szolgál, amelyek mindegyike a megengedett szerepkörök listájával egy HTTP-metódus hozzáférés-vezérlését jelenti.

A konténer ezután minden egyesnél ellenőrizni fogja URL-minta és HTTP módszer, ha a csatlakoztatott felhasználónak megvan a megfelelő szerepe az erőforrás eléréséhez.

4. Identity Store

Ezt a tulajdonságot elvonták a IdentityStore felület, és a hitelesítő adatok hitelesítésére, és végül a csoporttagság lekérésére szolgál. Más szavakkal: képes hitelesítésre, engedélyezésre vagy mindkettőre.

IdentityStore célja és ösztönzése a HttpAuthenticationMecanism egy hívott keresztül IdentityStoreHandler felület. A. Alapértelmezett megvalósítása IdentityStoreHandler a Servlet biztosítjatartály.

Egy alkalmazás biztosíthatja a IdentityStore vagy a tároló által biztosított két beépített megvalósítás egyikét használja az adatbázis és az LDAP számára.

4.1. Beépített azonosító üzletek

A Jakarta EE kompatibilis szervernek biztosítania kell a megvalósításokat a a két Identity Store: Adatbázis és LDAP.

Az adatbázis IdentityStore a megvalósítást egy konfigurációs adatoknak az @DataBaseIdentityStoreDefinition kommentár:

@DatabaseIdentityStoreDefinition (dataSourceLookup = "java: comp / env / jdbc / securityDS", callerQuery = "Jelszó kiválasztása azoktól a felhasználóktól, ahol felhasználónév =?", GroupsQuery = "Válassza ki a CSOPORTNEVET azokból a csoportokból, ahol felhasználónév =?", Prioritás = 30) @ApplicationScoped public osztály AppConfig {}

Konfigurációs adatként JNDI adatforrásra van szükségünk egy külső adatbázishoz, két JDBC utasítás állítja be a hívó és csoportjait, és végül egy prioritási paraméter, amelyet a többszörös tárolás esetén használunk.

IdentityStore nagy prioritással később a IdentityStoreHandler.

Mint az adatbázis, Az LDAP IdentityStore megvalósítását az @LdapIdentityStoreDefinition konfigurációs adatok átadásával:

@LdapIdentityStoreDefinition (url = "ldap: // localhost: 10389", callerBaseDn = "ou = hívó, dc = baeldung, dc = com", groupSearchBase = "ou = csoport, dc = baeldung, dc = com", groupSearchFilter = " (& (member =% s) (objectClass = groupOfNames)) ") @ApplicationScoped nyilvános osztály AppConfig {}

Itt szükségünk van egy külső LDAP-kiszolgáló URL-jére, arra, hogyan keressük meg a hívót az LDAP könyvtárban, és hogyan lehívjuk csoportjait.

4.2. Egyéni megvalósítása IdentityStore

A IdentityStore Az interfész négy alapértelmezett módszert határoz meg:

alapértelmezett CredentialValidationResult érvényesítés (hitelesítési adatok) alapértelmezett get getallergroups (CredentialValidationResult validationResult) alapértelmezett int prioritás () alapértelmezett validationTypes ()

A kiemelten fontos() A metódus visszaadja az iterációs sorrend értékét, amelyet ez a megvalósítás feldolgoz IdentityStoreHandler. An IdentityStore alacsonyabb prioritással kezelik először.

Alapértelmezés szerint egy IdentityStore feldolgozza a hitelesítő adatok hitelesítését (ValidationType.VALIDATE) és csoportos visszakeresés (ValidationType.PROVIDE_GROUPS). Ezt a viselkedést felülírhatjuk, hogy csak egy képességet tudjon biztosítani.

Így konfigurálhatjuk a IdentityStore csak hitelesítő adatok hitelesítésére használható:

@Override public Set validationTypes () {return EnumSet.of (ValidationType.VALIDATE); }

Ebben az esetben biztosítanunk kell a érvényesít() módszer:

@ApplicationScoped public class Az InMemoryIdentityStore megvalósítja az IdentityStore {// init fájlt vagy harcoded privát Map felhasználók = new HashMap (); @Orride public int priority () {return 70; } @Override public Set validationTypes () {return EnumSet.of (ValidationType.VALIDATE); } public CredentialValidationResult validate (UsernamePasswordCredential credential) {UserDetails user = users.get (credential.getCaller ()); if (credential.compareTo (user.getLogin (), user.getPassword ())) {return new CredentialValidationResult (user.getLogin ()); } return INVALID_RESULT; }}

Vagy választhatjuk a IdentityStore hogy csak csoportos visszakeresésre használható:

@Override public Set validationTypes () {return EnumSet.of (ValidationType.PROVIDE_GROUPS); }

Ezután biztosítanunk kell a getCallerGroups () mód:

@ApplicationScoped public class Az InMemoryIdentityStore megvalósítja az IdentityStore {// init fájlt vagy harcoded privát Map felhasználók = new HashMap (); @Orride public int priority () {return 90; } @Override public Set validationTypes () {return EnumSet.of (ValidationType.PROVIDE_GROUPS); } @ Nyilvános felülbírálás getCallerGroups (CredentialValidationResult validationResult) {UserDetails user = users.get (validationResult.getCallerPrincipal (). GetName ()); return new HashSet (user.getRoles ()); }}

Mivel IdentityStoreHandler a megvalósítást CDI-babnak várja, ezzel díszítjük ApplicationScoped annotáció.

5. Biztonsági környezet API

A Jakarta EE 8 Security API biztosítja hozzáférési pont az automatizált biztonsághoz a SecurityContext felület. Alternatív megoldás, ha a tároló által érvényesített deklaratív biztonsági modell nem elegendő.

A. Alapértelmezett megvalósítása SecurityContext az interfészt futás közben kell biztosítani CDI-babként, ezért be kell adnunk azt:

@Inject SecurityContext securityContext;

Ezen a ponton hitelesíthetjük a felhasználót, lehívhatunk egy hitelesítettet, ellenőrizhetjük szerepkör tagságát, és megadhatunk vagy megtagadhatunk hozzáférést a webes erőforráshoz az öt elérhető módszer segítségével.

5.1. Hívóadatok lekérése

A Jakarta EE korábbi verzióiban a vagy minden tárolóban másként ellenőrizze a szerepkör tagságát.

Amíg használjuk a getUserPrincipal () és isUserInRole () módszerei HttpServletRequest servlet tartályban, hasonló módszerekkel getCallerPrincipal () és isCallerInRole () metódusok a EJBContext az EJB konténerben használják.

Az új Jakarta EE 8 Security API ezt szabványosította által hasonló módszer biztosítása a SecurityContext felület:

Fő getCallerPrincipal (); logikai isCallerInRole (karakterlánc-szerepkör); A getPrincipalsByType (Osztálytípus) beállítása;

A getCallerPrincipal () metódus a hitelesített hívó fél konténerspecifikus ábráját adja vissza, míg a getPrincipalsByType () A módszer lekéri az adott típusú összes főt.

Hasznos lehet abban az esetben, ha az alkalmazásspecifikus hívó fél eltér a tárolótól.

5.2. Webes erőforrás-hozzáférés tesztelése

Először konfigurálnunk kell egy védett erőforrást:

@WebServlet ("/ protectedServlet") @ServletSecurity (@HttpConstraint (roleAllowed = "USER_ROLE")) nyilvános osztály ProtectedServlet kiterjeszti HttpServlet {// ...}

És akkor a védett erőforráshoz való hozzáférés ellenőrzéséhez meg kell hívnunk a hasAccessToWebResource () metódus:

securityContext.hasAccessToWebResource ("/ protectedServlet", "GET");

Ebben az esetben a metódus true-val tér vissza, ha a felhasználó szerepben van USER_ROLE.

5.3. A hívó fél programozott hitelesítése

Egy alkalmazás meghívásával programozottan elindíthatja a hitelesítési folyamatot hitelesítés ():

AuthenticationStatus hitelesítés (HttpServletRequest kérés, HttpServletResponse válasz, AuthenticationParameters paraméterek);

Ezután a tároló értesítést kap, és viszont meghívja az alkalmazáshoz konfigurált hitelesítési mechanizmust. AuthenticationParameters paraméter hitelesítő adatot ad a HttpAuthenticationMechanism:

withParams (). hitelesítő adat (hitelesítő adat)

A SIKER és SEND_FAILURE értékei AuthenticationStatus tervezzen sikeres és sikertelen hitelesítést SEND_CONTINUE jelzi a hitelesítési folyamat folyamatban lévő állapotát.

6. A példák futtatása

Ezeknek a példáknak a kiemelésére az Open Liberty Server legújabb fejlesztési verzióját használtuk, amely támogatja a Jakarta EE 8 alkalmazást. Ez a liberty-maven-pluginnak köszönhetően tölthető le és telepíthető, amely szintén telepítheti az alkalmazást és elindíthatja a szervert.

A példák futtatásához csak hozzáférjen a megfelelő modulhoz, és hívja meg ezt a parancsot:

mvn clean package liberty: futtatás

Ennek eredményeként a Maven letölti a szervert, felépíti, telepíti és futtatja az alkalmazást.

7. Következtetés

Ebben a cikkben kitértünk az új Jakarta EE 8 Security API fő jellemzőinek konfigurálására és megvalósítására.

Először azzal kezdtük, hogy bemutatjuk, hogyan kell konfigurálni az alapértelmezett beépített hitelesítési mechanizmusokat, és hogyan kell végrehajtani egy egyedi mechanizmust. Később láttuk, hogyan kell konfigurálni a beépített Identity Store-t, és hogyan lehet egy egyedi megvalósítani. És végül láttuk, hogyan hívhatjuk a SecurityContext.

Mint mindig, a cikk kódpéldái is elérhetők a GitHubon.