Vodič za Java uslugu provjere autentičnosti i autorizacije (JAAS)

Java Top

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ

1. Pregled

Java Authentication And Autorization Service (JAAS) je Java SE sigurnosni okvir niske razine koji povećava sigurnosni model sa sigurnosne zaštite temeljene na kodu do sigurnosti temeljene na korisniku. JAAS možemo koristiti u dvije svrhe:

  • Autentifikacija: Identificiranje entiteta koji trenutno pokreće kôd
  • Ovlaštenje: Nakon provjere autentičnosti osigurajte da ovaj entitet ima potrebna prava ili dozvole za kontrolu pristupa za izvršavanje osjetljivog koda

U ovom ćemo uputstvu pokriti kako postaviti JAAS u uzorku aplikacije implementirajući i konfigurirajući njegove različite API-je, posebno LoginModule.

2. Kako JAAS djeluje

Kada se JAAS koristi u aplikaciji, uključeno je nekoliko API-ja:

  • CallbackHandler: Koristi se za prikupljanje korisničkih vjerodajnica i po izboru pruža prilikom izrade LoginContext
  • Konfiguracija: Odgovoran za utovar LoginModule implementacije i po želji se mogu dobiti na LoginContext stvaranje
  • LoginModule: Učinkovito se koristi za provjeru autentičnosti korisnika

Upotrijebit ćemo zadanu implementaciju za Konfiguracija API i pružamo vlastite implementacije za CallbackHandler i LoginModule Apis.

3. Pružanje CallbackHandler Provedba

Prije kopanja u LoginModule provedbu, prvo moramo osigurati provedbu za CallbackHandler sučelje koje se koristi za prikupljanje korisničkih vjerodajnica.

Ima jednu metodu, ručka (), koji prihvaća niz Uzvratiti pozivs. Osim toga, JAAS već nudi mnoge Uzvratiti poziv implementacije, a mi ćemo koristiti NameCallback i PasswordCallback za prikupljanje korisničkog imena i lozinke.

Pogledajmo našu provedbu CallbackHandler sučelje:

javna klasa ConsoleCallbackHandler implementira CallbackHandler {@Override javna ručka za poništavanje (Callback [] callback) baca UnsupportedCallbackException {Console console = System.console (); za (povratni poziv: povratni poziv) {if (primjer povratnog poziva NameCallback) {NameCallback nameCallback = (NameCallback) povratni poziv; nameCallback.setName (console.readLine (nameCallback.getPrompt ())); } else if (primjer povratnog poziva PasswordCallback) {PasswordCallback passwordCallback = (PasswordCallback) povratni poziv; passwordCallback.setPassword (console.readPassword (passwordCallback.getPrompt ())); } else {baciti novi UnsupportedCallbackException (povratni poziv); }}}}

Dakle, za traženje i čitanje korisničkog imena koristili smo:

NameCallback nameCallback = (NameCallback) povratni poziv; nameCallback.setName (console.readLine (nameCallback.getPrompt ()));

Slično tome, za traženje i čitanje lozinke:

PasswordCallback passwordCallback = (PasswordCallback) povratni poziv; passwordCallback.setPassword (console.readPassword (passwordCallback.getPrompt ()));

Kasnije ćemo vidjeti kako nazvati CallbackHandler prilikom provedbe LoginModule.

4. Pružanje LoginModule Provedba

Radi jednostavnosti pružit ćemo implementaciju koja pohranjuje kodirane korisnike. Pa, nazovimo to InMemoryLoginModule:

javna klasa InMemoryLoginModule implementira LoginModule {private static final String USERNAME = "testuser"; privatni statički završni niz PASSWORD = "testpassword"; privatni subjekt Predmet; privatni CallbackHandler callbackHandler; privatna karta sharedState; opcije privatne karte; privatna logička prijavaSucceeded = false; privatni Glavni korisnikPrincipal; // ...}

U sljedećim pododjeljcima dat ćemo implementaciju za važnije metode: inicijalizirati (), prijaviti se(), i počiniti().

4.1. inicijalizirati ()

The LoginModule prvo se učitava, a zatim inicijalizira s Predmet i a CallbackHandler. Dodatno, LoginModulemogu koristiti a Karta za međusobnu razmjenu podataka i još jedan Karta za spremanje privatnih podataka o konfiguraciji:

javna void inicijalizacija (Subject subject, CallbackHandler callbackHandler, Map sharedState, opcije karte) {this.subject = subject; this.callbackHandler = callbackHandler; this.sharedState = sharedState; this.options = opcije; }

4.2. prijaviti se()

U prijaviti se() metodom, pozivamo se na CallbackHandler.handle () metoda s a NameCallback i a PasswordCallback zatražiti i dobiti korisničko ime i lozinku. Zatim uspoređujemo ove pružene vjerodajnice s onima s kodiranim podacima:

@Override public boolean login () baca LoginException {NameCallback nameCallback = new NameCallback ("username:"); PasswordCallback passwordCallback = novi PasswordCallback ("lozinka:", netačno); isprobajte {callbackHandler.handle (novi povratni poziv [] {nameCallback, passwordCallback}); Niz korisničko ime = nameCallback.getName (); Lozinka niza = novi niz (passwordCallback.getPassword ()); if (USERNAME.equals (korisničko ime) && PASSWORD.equals (lozinka)) {loginSucceeded = true; }} catch (IOException | UnsupportedCallbackException e) {// ...} return loginSucceeded; }

The prijaviti se() metoda bi se trebala vratiti pravi za uspješnu operaciju i lažno za neuspjelu prijavu.

4.3. počiniti()

Ako svi pozivi na LoginModule # prijava uspijemo, mi ažurirajte Predmet s dodatnim Glavni:

@Override public boolean commit () baca LoginException {if (! LoginSucceeded) {return false; } userPrincipal = novi UserPrincipal (korisničko ime); subject.getPrincipals (). add (userPrincipal); povratak istinit; }

Inače, prekid() metoda se naziva.

U ovom trenutku naš LoginModule implementacija je spremna i treba je konfigurirati tako da se može dinamički učitavati pomoću Konfiguracija davatelj usluga.

5. LoginModule Konfiguracija

JAAS koristi Konfiguracija davatelja usluga za učitavanje LoginModules tijekom izvođenja. Prema zadanim postavkama pruža i koristi ConfigFile provedba gdje LoginModuleKonfiguriraju se putem datoteke za prijavu. Na primjer, ovdje je sadržaj datoteke koja se koristi za naš LoginModule:

jaasApplication {com.baeldung.jaas.loginmodule.InMemoryLoginModule potreban debug = true; };

Kao što vidimo, dali smo potpuno kvalificirano ime razreda LoginModule provedba, a potreban zastavicu i mogućnost za uklanjanje pogrešaka.

Na kraju, imajte na umu da datoteku za prijavu možemo odrediti i putem java.security.auth.login.config svojstvo sustava:

$ java -Djava.security.auth.login.config = src / main / resources / jaas / jaas.login.config

Također možemo odrediti jednu ili više datoteka za prijavu putem svojstva login.config.url u Java sigurnosnoj datoteci, $ {java.home} /jre/lib/security/java.security:

login.config.url.1 = datoteka: $ {user.home} /. java.login.config

6. Autentifikacija

Prvo, aplikacija pokreće postupak provjere autentičnosti stvaranjem a LoginContext primjer. Da bismo to učinili, možemo pogledati cjeloviti konstruktor kako bismo imali ideju o tome što trebamo kao parametre:

LoginContext (naziv niza, subjekt predmeta, callbackhandler callbackhandler, konfiguracija konfiguracije)
  • Ime: koristi se kao indeks za učitavanje samo odgovarajućeg LoginModules
  • predmet: predstavlja korisnika ili uslugu koji se žele prijaviti
  • callbackHandler: odgovoran za prosljeđivanje vjerodajnica korisnika iz aplikacije u LoginModule
  • konfiguracija: odgovoran za utovar LoginModules koji odgovaraju parametru imena

Ovdje ćemo koristiti preopterećeni konstruktor gdje ćemo pružiti svoj CallbackHandler provedba:

LoginContext (naziv niza, CallbackHandler callbackHandler)

Sad kad imamo CallbackHandler i konfiguriran LoginModule, postupak autentifikacije možemo započeti inicijalizacijom a LoginContext objekt:

LoginContext loginContext = novi LoginContext ("jaasApplication", novi ConsoleCallbackHandler ());

U ovom trenutku, možemo se pozvati na prijaviti se() metoda za autentifikaciju korisnika:

loginContext.login ();

The prijaviti se() metoda, pak, stvara novu instancu našeg LoginModule i naziva svoje prijaviti se() metoda. I, nakon uspješne provjere autentičnosti možemo doći do provjere autentičnosti Predmet:

Subject subject = loginContext.getSubject ();

Ajmo sada pokrenuti primjer aplikacije koja ima LoginModule ožičeno:

$ mvn clean package $ java -Djava.security.auth.login.config = src / main / resources / jaas / jaas.login.config \ -classpath target / core-java-security-2-0.1.0-SNAPSHOT.jar com.baeldung.jaas.JaasAuthentication

Kad se od nas zatraži da navedete korisničko ime i lozinku, koristit ćemo testuser i testpassword kao vjerodajnice.

7. Odobrenje

Odobrenje stupa na snagu kada se korisnik prvi put poveže i poveže s AccessControlContext. Korištenjem Java sigurnosne politike možemo dodijeliti jedno ili više prava kontrole pristupa Glavnis. Tada možemo spriječiti pristup osjetljivom kodu pozivanjem mreže SecurityManager # checkPermission metoda:

SecurityManager.checkPermission (dozvola dozvole)

7.1. Definiranje dozvola

Pravo kontrole pristupa ili dopuštenje je sposobnost izvršavanja radnje na resursu. Dozvolu možemo primijeniti podklasiranjem Dopuštenje apstraktni razred. Da bismo to učinili, trebamo navesti naziv resursa i skup mogućih radnji. Na primjer, možemo koristiti FilePermission za konfiguriranje prava nadzora pristupa datotekama. Moguće radnje su čitati, pisati, izvršiti, i tako dalje. Za scenarije u kojima radnje nisu potrebne, možemo jednostavno koristiti BasicPermision.

Dalje ćemo pružiti provedbu dopuštenja putem ResourcePermission klasa u kojoj korisnici mogu imati dozvolu za pristup resursu:

javna završna klasa ResourcePermission proširuje BasicPermission {public ResourcePermission (naziv niza) {super (ime); }}

Kasnije ćemo konfigurirati unos za ovo dopuštenje putem Java sigurnosnih pravila.

7.2. Davanje dozvola

Obično ne trebamo znati sintaksu datoteke pravila, jer je uvijek možemo koristiti za izradu alata Policy Policy. Pogledajmo našu datoteku s pravilima:

dodijeliti glavnicu com.sun.security.auth.UserPrincipal testuser {dozvola com.baeldung.jaas.ResourcePermission "test_resource"};

U ovom uzorku, odobrili smo test_resource dopuštenje za testuser korisnik.

7.3. Provjera dozvola

Jednom Predmet je provjerena autentičnost i konfigurirana su dopuštenja, pristup možemo provjeriti pozivom na Predmet # doAs ili Predmet # doAsPrivilieged statičke metode. U tu svrhu pružit ćemo a Povlašteno djelovanje gdje možemo zaštititi pristup osjetljivom kodu. U trčanje() metodu, nazivamo SecurityManager # checkPermission metoda koja osigurava da ovjereni korisnik ima test_resource dopuštenje:

javna klasa ResourceAction implementira PrivilegedAction {@ Override public Object run () {SecurityManager sm = System.getSecurityManager (); if (sm! = null) {sm.checkPermission (novi ResourcePermission ("test_resource")); } System.out.println ("Imam pristup test_resource!"); return null; }}

Posljednja stvar je nazvati Predmet # doAsPrivileged metoda:

Subject subject = loginContext.getSubject (); PrivilegedAction privilegedAction = novo ResourceAction (); Subject.doAsPrivileged (subjekt, privilegiranoAction, null);

Kao i provjera autentičnosti, pokrenut ćemo i jednostavnu aplikaciju za autorizaciju u kojoj, uz LoginModule, pružamo datoteku za konfiguraciju dozvola:

$ mvn čist paket $ java -Djava.security.manager -Djava.security.policy = src / main / resources / jaas / jaas.policy \ -Djava.security.auth.login.config = src / main / resources / jaas / jaas.login.config \ -classpath target / core-java-security-2-0.1.0-SNAPSHOT.jar com.baeldung.jaas.JaasAuthorization

8. Zaključak

U ovom smo članku prikazali kako implementirati JAAS istražujući glavne klase i sučelja i pokazujući kako ih konfigurirati. Posebno smo implementirali davatelja usluga LoginModule.

Kao i obično, kôd u ovom članku dostupan je na GitHubu.

Dno Java

Upravo sam najavio novo Uči proljeće tečaj, usredotočen na osnove Spring 5 i Spring Boot 2:

>> PROVJERITE TEČAJ