Veiledning til Java Authentication And Authorization Service (JAAS)

Java Top

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET

1. Oversikt

Java Authentication And Authorization Service (JAAS) er et Java SE-sikkerhetsrammer på lavt nivå som utvider sikkerhetsmodellen fra kodebasert sikkerhet til brukerbasert sikkerhet. Vi kan bruke JAAS for to formål:

  • Autentisering: Identifiserer enheten som for øyeblikket kjører koden
  • Autorisasjon: Når den er godkjent, må du sørge for at denne enheten har de nødvendige tilgangskontrollettighetene eller tillatelsene for å utføre sensitiv kode

I denne opplæringen vil vi dekke hvordan du konfigurerer JAAS i et eksempel på en applikasjon ved å implementere og konfigurere de forskjellige API-ene, spesielt LoginModule.

2. Hvordan JAAS fungerer

Når du bruker JAAS i en applikasjon, er flere API-er involvert:

  • CallbackHandler: Brukes til å samle brukerlegitimasjon og eventuelt oppgitt når du oppretter InnloggingContext
  • Konfigurasjon: Ansvarlig for lasting LoginModule implementeringer og kan valgfritt leveres på InnloggingContext opprettelse
  • LoginModule: Effektivt brukt for å autentisere brukere

Vi bruker standardimplementeringen for Konfigurasjon API og gi våre egne implementeringer for CallbackHandler og LoginModule APIer.

3. Å gi CallbackHandler Gjennomføring

Før du graver i LoginModule implementering, må vi først gi en implementering for CallbackHandler grensesnitt, som brukes til å samle brukerlegitimasjon.

Den har en enkelt metode, håndtak(), som godtar en rekke Ring tilbakes. I tillegg gir JAAS allerede mange Ring tilbake implementeringer, og vi bruker NameCallback og PasswordCallback for å samle henholdsvis brukernavn og passord.

La oss se gjennomføringen av CallbackHandler grensesnitt:

offentlig klasse ConsoleCallbackHandler implementerer CallbackHandler {@Override public void handle (Callback [] callbacks) kaster UnsupportedCallbackException {Console console = System.console (); for (Callback callback: callbacks) {if (callback instanceof NameCallback) {NameCallback nameCallback = (NameCallback) callback; nameCallback.setName (console.readLine (nameCallback.getPrompt ())); } ellers hvis (tilbakeringing av PasswordCallback) {PasswordCallback passwordCallback = (PasswordCallback) tilbakeringing; passwordCallback.setPassword (console.readPassword (passwordCallback.getPrompt ())); } annet {kast nytt UnsupportedCallbackException (tilbakeringing); }}}}

Så, for å spørre og lese brukernavnet, har vi brukt:

NameCallback nameCallback = (NameCallback) tilbakeringing; nameCallback.setName (console.readLine (nameCallback.getPrompt ()));

På samme måte for å be og lese passordet:

PasswordCallback passwordCallback = (PasswordCallback) tilbakeringing; passwordCallback.setPassword (console.readPassword (passwordCallback.getPrompt ()));

Senere får vi se hvordan vi kan ringe CallbackHandler når du implementerer LoginModule.

4. Å gi LoginModule Gjennomføring

For enkelhets skyld vil vi tilby en implementering som lagrer hardkodede brukere. Så, la oss kalle det InMemoryLoginModule:

offentlig klasse InMemoryLoginModule implementerer LoginModule {privat statisk sluttstreng USERNAME = "testbruker"; privat statisk slutt String PASSWORD = "testpassword"; privat emne; private CallbackHandler callbackHandler; privat kart delt stat; private kartalternativer; privat boolsk loginSucceeded = false; privat Hovedbruker Rektor; // ...}

I de neste underavsnittene vil vi implementere de viktigere metodene: initialisere (), Logg Inn(), og begå().

4.1. initialisere ()

De LoginModule lastes først og initialiseres deretter med a Emne og en CallbackHandler. I tillegg LoginModules kan bruke en Kart for å dele data mellom seg, og en annen Kart for lagring av private konfigurasjonsdata:

initialt tomrom initialiseres (Emneemne, CallbackHandler tilbakeringingHandler, Map sharedState, Kartalternativer) {this.subject = subject; this.callbackHandler = callbackHandler; this.sharedState = delt stat; this.options = alternativer; }

4.2. Logg Inn()

I Logg Inn() metoden, påkaller vi CallbackHandler.handle () metode med en NameCallback og en PasswordCallback for å spørre og få brukernavnet og passordet. Deretter sammenligner vi disse opplysningene med de hardkodede:

@ Override offentlig boolsk pålogging () kaster LoginException {NameCallback nameCallback = new NameCallback ("brukernavn:"); PasswordCallback passwordCallback = nytt PasswordCallback ("passord:", falsk); prøv {callbackHandler.handle (ny tilbakeringing [] {nameCallback, passwordCallback}); String brukernavn = nameCallback.getName (); Strengpassord = ny streng (passwordCallback.getPassword ()); hvis (USERNAME.equals (brukernavn) && PASSWORD.equals (passord)) {loginSucceeded = true; }} fange (IOException | Ikke støttetCallbackException e) {// ...} return loginSucceeded; }

De Logg Inn() metoden skal komme tilbake ekte for en vellykket operasjon og falsk for en mislykket pålogging.

4.3. begå()

Hvis alle ringer til LoginModule # login lykkes, vi oppdater Emne med et tillegg Rektor:

@Override public boolean commit () kaster LoginException {if (! LoginSucceeded) {return false; } userPrincipal = ny UserPrincipal (brukernavn); subject.getPrincipals (). add (userPrincipal); returner sant; }

Ellers kan den avbryte() metoden kalles.

På dette punktet, vår LoginModule implementeringen er klar og må konfigureres slik at den kan lastes dynamisk ved hjelp av Konfigurasjon tjenesteleverandør.

5. LoginModule Konfigurasjon

JAAS bruker Konfigurasjon tjenesteleverandøren å laste inn LoginModules ved kjøretid. Som standard gir og bruker den ConfigFile implementering hvor LoginModules er konfigurert gjennom en påloggingsfil. Her er for eksempel innholdet i filen som brukes til vår LoginModule:

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

Som vi kan se, vi har gitt det fullt kvalifiserte klassenavnet til LoginModule gjennomføring, a kreves flagg, og et alternativ for feilsøking.

Til slutt, merk at vi også kan spesifisere påloggingsfilen gjennom java.security.auth.login.config systemegenskap:

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

Vi kan også spesifisere en eller flere påloggingsfiler gjennom eiendommen login.config.url i Java-sikkerhetsfilen, $ {java.home} /jre/lib/security/java.security:

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

6. Autentisering

For det første, et program initialiserer autentiseringsprosessen ved å opprette en InnloggingContext forekomst. For å gjøre det kan vi se på hele konstruktøren for å få en idé om hva vi trenger som parametere:

LoginContext (String name, Subject subject, CallbackHandler callbackHandler, Configuration config)
  • Navn: brukes som en indeks for kun å laste inn den tilsvarende LoginModules
  • Emne: representerer en bruker eller tjeneste som ønsker å logge på
  • tilbakeringingHandler: ansvarlig for å overføre brukerlegitimasjon fra applikasjonen til LoginModule
  • config: ansvarlig for lasting LoginModules som tilsvarer navneparameteren

Her bruker vi den overbelastede konstruktøren der vi skal gi oss CallbackHandler gjennomføring:

LoginContext (String name, CallbackHandler callbackHandler)

Nå som vi har en CallbackHandler og en konfigurert LoginModule, vi kan starte godkjenningsprosessen ved å initialisere a InnloggingContext gjenstand:

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

På dette punktet, vi kan påberope oss Logg Inn() metode for å autentisere brukeren:

loginContext.login ();

De Logg Inn() metoden skaper i sin tur en ny forekomst av vår LoginModule og kaller sin Logg Inn() metode. Og, etter vellykket autentisering kan vi hente den godkjente Emne:

Emneemne = loginContext.getSubject ();

La oss nå kjøre et eksempel på et program som har LoginModule kablet i:

$ mvn ren pakke $ 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

Når vi blir bedt om å oppgi brukernavn og passord, bruker vi det testbruker og testpassord som legitimasjon.

7. Autorisasjon

Autorisasjon spiller inn når brukeren først blir koblet til og assosiert med AccessControlContext. Ved hjelp av Java-sikkerhetspolitikken kan vi gi en eller flere rettigheter til tilgangskontroll til Rektors. Vi kan da forhindre tilgang til sensitiv kode ved å ringe SecurityManager # checkPermission metode:

SecurityManager.checkPermission (tillatelse perm)

7.1. Definere tillatelser

En adgangskontrollrett eller tillatelse er muligheten til å utføre en handling på en ressurs. Vi kan implementere en tillatelse ved å underklassere Tillatelse abstrakt klasse. For å gjøre dette må vi oppgi et ressursnavn og et sett med mulige handlinger. For eksempel kan vi bruke FilePermission for å konfigurere rettigheter for tilgangskontroll på filer. Mulige handlinger er lese, skrive, henrette, og så videre. For scenarier der handlinger ikke er nødvendige, kan vi bare bruke BasicPermision.

Deretter gir vi en implementering av tillatelse gjennom ResourcePermission klasse der brukere kan ha tillatelse til å få tilgang til en ressurs:

offentlig sluttklasse ResourcePermission utvider BasicPermission {public ResourcePermission (String name) {super (name); }}

Senere konfigurerer vi en oppføring for denne tillatelsen gjennom Java-sikkerhetspolitikken.

7.2. Gi tillatelser

Vanligvis trenger vi ikke å kjenne syntaksen for policyfiler fordi vi alltid kan bruke Policy Tool til å lage en. La oss ta en titt på policyfilen vår:

gi rektor com.sun.security.auth.UserPrincipal testbruker {tillatelse com.baeldung.jaas.ResourcePermission "test_resource"};

I dette eksemplet, vi har gitt testressurs tillatelse til testbruker bruker.

7.3. Kontrollerer tillatelser

Først når Emne er autentisert og tillatelser er konfigurert, vi kan se etter tilgang ved å ringe Emne # doAs eller Emne # doAsPrivilieged statiske metoder. For dette formålet vil vi gi en PrivilegedAction der vi kan beskytte tilgangen til sensitiv kode. I løpe() metoden, kaller vi SecurityManager # checkPermission metode for å sikre at den autentiserte brukeren har testressurs tillatelse:

offentlig klasse ResourceAction implementerer PrivilegedAction {@Override public Object run () {SecurityManager sm = System.getSecurityManager (); hvis (sm! = null) {sm.checkPermission (ny ResourcePermission ("test_resource")); } System.out.println ("Jeg har tilgang til testressurs!"); return null; }}

Det siste er å ringe Emne # doAsPrivileged metode:

Emneemne = loginContext.getSubject (); PrivilegedAction privilegedAction = ny ResourceAction (); Subject.doAsPrivileged (subject, privilegedAction, null);

I likhet med godkjenningen kjører vi en enkel applikasjon for autorisasjonen der, i tillegg til LoginModule, vi gir en konfigurasjonsfil for tillatelser:

$ mvn ren pakke $ 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. Konklusjon

I denne artikkelen har vi vist hvordan du implementerer JAAS ved å utforske de viktigste klassene og grensesnittene og vise hvordan du konfigurerer dem. Spesielt har vi implementert en tjenesteleverandør LoginModule.

Som vanlig er koden i denne artikkelen tilgjengelig på GitHub.

Java bunn

Jeg kunngjorde nettopp det nye Lær våren kurs, med fokus på det grunnleggende i vår 5 og vårstøvel 2:

>> KONTROLLER KURSET