Jakarta EE 8 Security API

1. Prehľad

Jakarta EE 8 Security API je nový štandard a prenosný spôsob riešenia bezpečnostných obáv v kontajneroch Java.

V tomto článku pozrieme sa na tri základné funkcie API:

  1. Mechanizmus autentifikácie HTTP
  2. Obchod identity
  3. Kontext bezpečnosti

Najprv pochopíme, ako nakonfigurovať poskytované implementácie a potom, ako implementovať vlastné.

2. Maven závislosti

Na nastavenie bezpečnostného API Jakarta EE 8 potrebujeme buď implementáciu poskytnutú serverom, alebo explicitnú.

2.1. Používanie implementácie servera

Servery kompatibilné s Jakarta EE 8 už poskytujú implementáciu bezpečnostného API Jakarta EE 8, a preto potrebujeme iba artefakt Jakarta EE Web Profile API Maven:

  poskytnutý javax javaee-web-api 8.0 

2.2. Pomocou explicitnej implementácie

Najskôr zadáme artefakt Maven pre bezpečnostné rozhranie Jakarta EE 8:

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

A potom pridáme implementáciu, napríklad Soteria - referenčnú implementáciu:

  org.glassfish.soteria javax.security.enterprise 1.0 

3. Mechanizmus autentifikácie HTTP

Pred programom Jakarta EE 8 sme nakonfigurovali mechanizmy overovania deklaratívne prostredníctvom servera web.xml spis.

V tejto verzii navrhlo Jakarta EE 8 Security API nové HttpAuthenticationMechanism rozhranie ako náhrada. Preto môžu webové aplikácie teraz konfigurovať mechanizmy autentifikácie poskytovaním implementácií tohto rozhrania.

Kontajner už našťastie poskytuje implementáciu pre každú z troch metód autentifikácie definovaných v špecifikácii servletu: základné autentifikácia HTTP, autentifikácia na základe formulára a vlastné autentifikácia na základe formulára.

Poskytuje tiež anotáciu na spustenie každej implementácie:

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

3.1. Základné autentifikácia HTTP

Ako už bolo spomenuté vyššie, webová aplikácia môže konfigurovať základné overenie HTTP iba ​​pomocou @BasicAuthenticationMechanismDefinícia anotácie na fazuli CDI:

@BasicAuthenticationMechanismDefinition (realmName = "userRealm") @ApplicationScoped verejná trieda AppConfig {}

V tomto okamihu kontajner Servlet prehľadá a vytvorí inštanciu poskytnutej implementácie HttpAuthenticationMechanism rozhranie.

Po prijatí neoprávnenej žiadosti vyzve kontajner klienta na poskytnutie vhodných autentifikačných informácií prostredníctvom servera WWW-autentifikácia hlavička odpovede.

WWW-autentifikácia: Základná sféra = "userRealm"

Klient potom pošle užívateľské meno a heslo, oddelené dvojbodkou „:“ a zakódované v Base64, cez Povolenie hlavička požiadavky:

// user = baeldung, password = baeldung Autorizácia: Základné YmFlbGR1bmc6YmFlbGR1bmc = 

Upozorňujeme, že dialógové okno na poskytnutie poverení pochádza z prehľadávača, nie zo servera.

3.2. Formulár založené na autentifikácii HTTP

The @FormAuthenticationMechanismDefinition anotácia spustí autentifikáciu na základe formulára ako je definované v špecifikácii servletu.

Potom máme možnosť určiť prihlasovacie a chybové stránky alebo použiť predvolené rozumné stránky /Prihlásiť sa a / login-error:

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

V dôsledku vyvolania loginPage, server by mal odoslať formulár klientovi:

Klient by potom mal odoslať formulár do preddefinovaného procesu autentifikácie pomocou zálohovania, ktorý poskytuje kontajner.

3.3. Vlastné overovanie pomocou protokolu HTTP na základe formulára

Webová aplikácia môže spustiť implementáciu vlastnej autentifikácie na základe formulára pomocou anotácie @CustomFormAuthenticationMechanismDefinition:

@CustomFormAuthenticationMechanismDefinition (loginToContinue = @LoginToContinue (loginPage = "/login.xhtml")) @ApplicationScoped verejná trieda AppConfig {}

Ale na rozdiel od predvoleného overovania na základe formulára, konfigurujeme vlastnú prihlasovaciu stránku a vyvolávame SecurityContext.authenticate () metóda ako proces autentizácie zálohovaním.

Poďme sa pozrieť na podklad LoginBean ktorý tiež obsahuje logiku prihlásenia:

@Named @RequestScoped verejná trieda LoginBean {@Inject private SecurityContext securityContext; @NotNull súkromné ​​meno používateľa reťazca; @NotNull súkromné ​​heslo reťazca; public void login () {poverenie poverenia = nové UsernamePasswordCredential (používateľské meno, nové heslo (heslo)); AuthenticationStatus status = securityContext .authenticate (getHttpRequestFromFacesContext (), getHttpResponseFromFacesContext (), withParams (). Credential (credential)); // ...} // ...}

V dôsledku vyvolania zvyku login.xhtml stránke klient odošle prijatý formulár na server LoginBean 's Prihlásiť sa() metóda:

//... 

3.4. Vlastný mechanizmus autentifikácie

The HttpAuthenticationMechanism rozhranie definuje tri metódy. Najdôležitejšie je validateRequest () ktoré musíme zabezpečiť implementáciu.

Predvolené správanie pre ďalšie dve metódy, secureResponse () a cleanSubject (), vo väčšine prípadov postačuje.

Pozrime sa na príklad implementácie:

@ApplicationScoped verejná trieda CustomAuthentication implementuje HttpAuthenticationMechanism {@Override public AuthenticationStatus validateRequest (požiadavka HttpServletRequest, odpoveď HttpServletResponse, HttpMessageContext httpMsgContext) hodí AuthenticationException {"String username =" username = "username =" Reťazec heslo = response.getParameter ("heslo"); // výsmech UserDetail, ale v skutočnom živote ho môžeme získať z databázy UserDetail userDetail = findByUserNameAndPassword (meno používateľa, heslo); if (userDetail! = null) {return httpMsgContext.notifyContainerAboutLogin (new CustomPrincipal (userDetail), new HashSet (userDetail.getRoles ())); } návrat httpMsgContext.responseUnauthorized (); } // ...}

Tu implementácia poskytuje obchodnú logiku procesu validácie, ale v praxi sa odporúča delegovať na IdentityStore cez IdentityStoreHandler br vzývanie potvrdiť.

Implementáciu sme tiež anotovali pomocou @ApplicationScoped anotáciu, pretože je potrebné, aby bola podporovaná technológiou CDI.

Po platnom overení poverenia a prípadnom získaní rolí používateľov, implementácia by mala potom upovedomiť kontajner:

HttpMessageContext.notifyContainerAboutLogin (hlavný zodpovedný, nastavenie skupín)

3.5. Presadzovanie zabezpečenia servletom

Webová aplikácia môže vynútiť bezpečnostné obmedzenia pomocou znaku @ServletSecurity anotácia k implementácii servletu:

@WebServlet ("/ zabezpečené") @ServletSecurity (hodnota = @HttpConstraint (roleAllowed = {"admin_role"}), httpMethodConstraints = {@HttpMethodConstraint (hodnota = "GET", roleAllowed = {"user_role"}), @Httpint = "POST", roleAllowed = {"admin_role"})}) verejná trieda SecuredServlet rozširuje HttpServlet {}

Táto anotácia má dva atribúty - httpMethodConstraints a hodnotu; httpMethodConstraints sa používa na zadanie jedného alebo viacerých obmedzení, z ktorých každý predstavuje riadenie prístupu k metóde HTTP zoznamom povolených rolí.

Kontajner potom skontroluje, či existuje vzor adresy URL a metóda HTTP, ak má pripojený používateľ vhodnú rolu na prístup k prostriedku.

4. Obchod s identitami

Túto vlastnosť abstraktuje the IdentityStore rozhranie a používa sa na overenie poverení a prípadné získanie členstva v skupine. Inými slovami, môže poskytnúť možnosti autentifikácie, autorizácie alebo oboje.

IdentityStore je určený a odporúčaný na použitie v HttpAuthenticationMecanism prostredníctvom volaného IdentityStoreHandler rozhranie. Predvolená implementácia IdentityStoreHandler je poskytovaný servletomkontajner.

Aplikácia môže poskytnúť svoju implementáciu IdentityStore alebo používa jednu z dvoch zabudovaných implementácií poskytovaných kontajnerom pre databázu a LDAP.

4.1. Vstavané obchody s identitami

Server kompatibilný s Jakarta EE by mal poskytovať implementácie pre server dva obchody identity: Databáza a LDAP.

Databáza IdentityStore implementácia sa inicializuje odovzdaním konfiguračných údajov do @DataBaseIdentityStoreDefinition anotácia:

@DatabaseIdentityStoreDefinition (dataSourceLookup = "java: comp / env / jdbc / securityDS", callerQuery = "vyberte heslo od používateľov, kde username =?", GroupsQuery = "vyberte GROUPNAME zo skupín, kde username =?", Priorita = 30) @ApplicationScoped public trieda AppConfig {}

Ako konfiguračné údaje potrebujeme zdroj údajov JNDI do externej databázy, sú nakonfigurované dva príkazy JDBC na kontrolu volajúceho a jeho skupín a nakoniec prioritný parameter, ktorý sa používa v prípade hromadného ukladania.

IdentityStore s vysokou prioritou neskôr spracuje IdentityStoreHandler.

Rovnako ako databáza, Implementácia LDAP IdentityStore sa inicializuje prostredníctvom @LdapIdentityStoreDefinition odovzdaním konfiguračných údajov:

@LdapIdentityStoreDefinition (url = "ldap: // localhost: 10389", callerBaseDn = "ou = volajúci, dc = baeldung, dc = com", groupSearchBase = "ou = skupina, dc = baeldung, dc = com", groupSearchFilter = " (& (member =% s) (objectClass = groupOfNames)) ") @ApplicationScoped verejná trieda AppConfig {}

Tu potrebujeme adresu URL externého servera LDAP, ako vyhľadávať volajúceho v adresári LDAP a ako načítať jeho skupiny.

4.2. Implementácia Custom IdentityStore

The IdentityStore rozhranie definuje štyri predvolené metódy:

default CredentialValidationResult validate (Credential credential) default Set getCallerGroups (CredentialValidationResult validationResult) default int priority () default Set validationTypes ()

The priorita () metóda vráti hodnotu pre poradie iterácie, ktorú táto implementácia spracuje IdentityStoreHandler. An IdentityStore najskôr sa zaobchádza s nižšou prioritou.

V predvolenom nastavení je IdentityStore spracuje validáciu oboch poverení (ValidationType.VALIDATE) a skupinové vyhľadávanie (ValidationType.PROVIDE_GROUPS). Toto správanie môžeme prepísať tak, aby poskytovalo iba jednu funkciu.

Môžeme teda nakonfigurovať IdentityStore použiť iba na overenie poverení:

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

V takom prípade by sme mali zabezpečiť implementáciu potvrdiť() metóda:

@ApplicationScoped verejná trieda InMemoryIdentityStore implementuje IdentityStore {// init zo súboru alebo harcoded súkromných používateľov mapy = nový HashMap (); @Override public int priority () {návrat 70; } @Override public Set validationTypes () {return EnumSet.of (ValidationType.VALIDATE); } verejné CredentialValidationResult validate (poverenie UsernamePasswordCredential) {UserDetails user = users.get (credential.getCaller ()); if (credential.compareTo (user.getLogin (), user.getPassword ())) {vrátiť nový CredentialValidationResult (user.getLogin ()); } vrátiť INVALID_RESULT; }}

Alebo sa môžeme rozhodnúť nakonfigurovať IdentityStore aby ho bolo možné použiť iba na skupinové vyhľadávanie:

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

Potom by sme mali zabezpečiť implementáciu getCallerGroups () metódy:

@ApplicationScoped verejná trieda InMemoryIdentityStore implementuje IdentityStore {// init zo súboru alebo harcoded súkromných používateľov mapy = nový HashMap (); @Override public int priority () {návrat 90; } @Override public Set validationTypes () {return EnumSet.of (ValidationType.PROVIDE_GROUPS); } @Override public Set getCallerGroups (CredentialValidationResult validationResult) {UserDetails user = users.get (validationResult.getCallerPrincipal (). GetName ()); vrátiť nový HashSet (user.getRoles ()); }}

Pretože IdentityStoreHandler očakáva, že implementácia bude fazuľa CDI, ktorú ozdobíme ApplicationScoped anotácia.

5. Bezpečnostné kontextové API

Zabezpečovacie rozhranie Jakarta EE 8 poskytuje - prístupový bod k programovej bezpečnosti prostredníctvom SecurityContext rozhranie. Je to alternatíva, keď deklaratívny model zabezpečenia vynútený kontajnerom nie je dostatočný.

Predvolená implementácia SecurityContext rozhranie by malo byť poskytované za behu ako fazuľa CDI, a preto ho musíme vložiť:

@Inject SecurityContext securityContext;

V tomto okamihu môžeme používateľa autentifikovať, získať autentifikovaného, ​​skontrolovať jeho členstvo v role a udeliť alebo zamietnuť prístup k webovému prostriedku pomocou piatich dostupných metód.

5.1. Načítanie údajov o volajúcom

V predchádzajúcich verziách Jakarta EE sme načítali Principal alebo skontrolujte členstvo v role inak v každom kontajneri.

Zatiaľ čo používame getUserPrincipal () a isUserInRole () metódy HttpServletRequest v servletovom kontajneri, podobné metódy getCallerPrincipal () a metódy isCallerInRole () z EJBContext sa používajú v kontajneri EJB.

Nové bezpečnostné rozhranie Jakarta EE 8 to štandardizovalo od poskytovanie podobnej metódy prostredníctvom SecurityContext rozhranie:

Principal getCallerPrincipal (); boolean isCallerInRole (reťazcová rola); Nastaviť getPrincipalsByType (typ triedy);

The getCallerPrincipal () metóda vracia špecifickú reprezentáciu autentifikovaného volajúceho, zatiaľ čo getPrincipalsByType () metóda získa všetkých principálov daného typu.

Môže to byť užitočné v prípade, že sa volajúci pre konkrétnu aplikáciu líši od volajúceho v kontajneri.

5.2. Testovanie prístupu k webovým zdrojom

Najskôr musíme nakonfigurovať chránený zdroj:

@WebServlet ("/ protectedServlet") @ServletSecurity (@HttpConstraint (roleAllowed = "USER_ROLE")) verejná trieda ProtectedServlet rozširuje HttpServlet {// ...}

A potom, aby sme skontrolovali prístup k tomuto chránenému prostriedku, mali by sme sa odvolať na metóda hasAccessToWebResource ():

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

V takom prípade metóda vráti hodnotu true, ak je používateľ v role USER_ROLE.

5.3. Programová autentifikácia volajúceho

Aplikácia môže programovo spustiť proces autentifikácie vyvolaním autentifikovať ():

AuthenticationStatus authenticate (požiadavka HttpServletRequest, odpoveď HttpServletResponse, parametre AuthenticationParameters);

Kontajner je potom upozornený a následne vyvolá mechanizmus autentifikácie nakonfigurovaný pre aplikáciu. AuthenticationParameters parameter poskytuje poverenie pre Mechanizmus HttpAuthentication:

withParams (). credential (poverenie)

The ÚSPECH a SEND_FAILURE hodnoty AuthenticationStatus navrhnúť úspešné a neúspešné overenie SEND_CONTINUE signalizuje prebiehajúci stav procesu autentifikácie.

6. Spustenie príkladov

Na zvýraznenie týchto príkladov sme použili najnovšiu vývojovú zostavu servera Open Liberty Server, ktorá podporuje Jakarta EE 8. Tento program sa sťahuje a inštaluje vďaka pluginu libty-maven-plugin, ktorý umožňuje nasadenie aplikácie a spustenie servera.

Príklady spustíte iba prístupom k príslušnému modulu a vyvolaním tohto príkazu:

mvn čistý balík sloboda: spustiť

Výsledkom bude, že Maven stiahne server, zostaví, nasadí a spustí aplikáciu.

7. Záver

V tomto článku sme sa venovali konfigurácii a implementácii hlavných funkcií nového bezpečnostného API Jakarta EE 8.

Najprv sme začali tým, že sme si ukázali, ako nakonfigurovať predvolené vstavané mechanizmy overovania a ako implementovať vlastný. Neskôr sme videli, ako nakonfigurovať vstavaný Identity Store a ako implementovať vlastný. A nakoniec sme videli, ako nazvať metódy SecurityContext.

Príklady kódov pre tento článok sú ako vždy dostupné na GitHub.


$config[zx-auto] not found$config[zx-overlay] not found