Vejledning til Java Authentication And Authorization Service (JAAS)

Java Top

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

1. Oversigt

Java Authentication And Authorization Service (JAAS) er en Java SE-sikkerhedsramme på lavt niveau forøger sikkerhedsmodellen fra kodebaseret sikkerhed til brugerbaseret sikkerhed. Vi kan bruge JAAS til to formål:

  • Godkendelse: Identificering af den enhed, der i øjeblikket kører koden
  • Autorisation: Når den er godkendt, skal du sikre dig, at denne enhed har de nødvendige adgangskontrolrettigheder eller tilladelser til at udføre følsom kode

I denne vejledning dækker vi, hvordan du konfigurerer JAAS i en prøveapplikation ved at implementere og konfigurere dens forskellige API'er, især LoginModul.

2. Hvordan JAAS fungerer

Når du bruger JAAS i en applikation, er flere API'er involveret:

  • CallbackHandler: Bruges til at indsamle brugeroplysninger og leveres valgfrit, når du opretter LoginContext
  • Konfiguration: Ansvarlig for indlæsning LoginModul implementeringer og kan valgfrit leveres på LoginContext skabelse
  • LoginModul: Effektivt brugt til godkendelse af brugere

Vi bruger standardimplementeringen til Konfiguration API og levere vores egne implementeringer til CallbackHandler og LoginModul API'er.

3. At yde CallbackHandler Implementering

Inden du graver ind i LoginModul implementering, skal vi først give en implementering af CallbackHandler interface, der bruges til at indsamle brugeroplysninger.

Det har en enkelt metode, håndtere(), der accepterer en række Ring tilbages. Derudover leverer JAAS allerede mange Ring tilbage implementeringer, og vi bruger NameCallback og PasswordCallback til indsamling af henholdsvis brugernavn og adgangskode.

Lad os se vores implementering af CallbackHandler grænseflade:

public class 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 (tilbagekaldelse af PasswordCallback) {PasswordCallback passwordCallback = (PasswordCallback) tilbagekald; passwordCallback.setPassword (console.readPassword (passwordCallback.getPrompt ())); } ellers {throw new UnsupportedCallbackException (callback); }}}}

Så for at spørge og læse brugernavnet har vi brugt:

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

Tilsvarende for at spørge og læse adgangskoden:

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

Senere vil vi se, hvordan vi kalder CallbackHandler ved implementering af LoginModul.

4. Leverer LoginModul Implementering

For enkelheds skyld leverer vi en implementering, der gemmer hardkodede brugere. Så lad os kalde det InMemoryLoginModule:

offentlig klasse InMemoryLoginModule implementerer LoginModule {privat statisk endelig streng USERNAME = "testbruger"; privat statisk endelig streng PASSWORD = "testpassword"; privat emne emne; privat CallbackHandler callbackHandler; privat kort sharedState; private kortindstillinger; privat boolsk loginSucceeded = false; privat hovedbruger hovedstol; // ...}

I de næste underafsnit giver vi en implementering af de mere vigtige metoder: initialisere (), Log på()og begå().

4.1. initialisere ()

Det LoginModul indlæses først og initialiseres derefter med en Emne og en CallbackHandler. Derudover LoginModuls kan bruge en Kort for at dele data indbyrdes og en anden Kort til lagring af private konfigurationsdata:

initialisering af offentligt tomrum (Emneemne, CallbackHandler callbackHandler, Map sharedState, Kortmuligheder) {this.subject = subject; this.callbackHandler = callbackHandler; this.sharedState = delt stat; this.options = muligheder; }

4.2. Log på()

I Log på() metode, påberåber vi os CallbackHandler.handle () metode med en NameCallback og en PasswordCallback for at spørge og få brugernavnet og adgangskoden. Derefter sammenligner vi disse leverede legitimationsoplysninger med de hårdkodede:

@ Override offentlig boolsk login () kaster LoginException {NameCallback nameCallback = nyt NameCallback ("brugernavn:"); PasswordCallback passwordCallback = nyt PasswordCallback ("password:", false); prøv {callbackHandler.handle (ny Callback [] {nameCallback, passwordCallback}); String brugernavn = nameCallback.getName (); Strengadgangskode = ny streng (passwordCallback.getPassword ()); hvis (USERNAME.equals (brugernavn) && PASSWORD.equals (password)) {loginSucceeded = true; }} fange (IOException | Ikke-understøttetCallbackException e) {// ...} return loginSucceeded; }

Det Log på() metoden skal vende tilbage rigtigt for en vellykket operation og falsk for et mislykket login.

4.3. begå()

Hvis alle ringer til LoginModule # login lykkes, vi opdatere Emne med en ekstra Rektor:

@Override public boolean commit () kaster LoginException {if (! LoginSucceeded) {return false; } userPrincipal = ny UserPrincipal (brugernavn); subject.getPrincipals (). tilføj (userPrincipal); returner sandt; }

Ellers er abort() metode kaldes.

På dette tidspunkt er vores LoginModul implementeringen er klar og skal konfigureres, så den kan indlæses dynamisk ved hjælp af Konfiguration service udbyder.

5. LoginModul Konfiguration

JAAS bruger Konfiguration tjenesteudbyder at indlæse LoginModuls ved kørselstid. Som standard leverer og bruger den ConfigFile implementering hvor LoginModuls er konfigureret via en loginfil. For eksempel er her indholdet af filen, der bruges til vores LoginModul:

jaasApplication {com.baeldung.jaas.loginmodule.InMemoryLoginModule krævet debug = true; };

Som vi kan se, Vi har angivet det fuldt kvalificerede klassenavn på LoginModul implementering, a krævet flag og en mulighed for fejlretning.

Endelig bemærk, at vi også kan specificere loginfilen gennem java.security.auth.login.config systemegenskab:

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

Vi kan også specificere en eller flere loginfiler gennem ejendommen login.config.url i Java-sikkerhedsfilen, $ {java.home} /jre/lib/security/java.security:

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

6. Godkendelse

For det første, en applikation initialiserer godkendelsesprocessen ved at oprette en LoginContext eksempel. For at gøre det kan vi se på den fulde konstruktør for at få en idé om, hvad vi har brug for som parametre:

LoginContext (String name, Subject subject, CallbackHandler callbackHandler, Configuration config)
  • navn: bruges som et indeks til kun at indlæse det tilsvarende LoginModuls
  • emne: repræsenterer en bruger eller tjeneste, der ønsker at logge ind
  • callbackHandler: ansvarlig for at videregive brugeroplysninger fra applikationen til LoginModul
  • config: ansvarlig for indlæsning LoginModuls, der svarer til navneparameteren

Her bruger vi den overbelastede konstruktør, hvor vi leverer vores CallbackHandler implementering:

LoginContext (String name, CallbackHandler callbackHandler)

Nu hvor vi har en CallbackHandler og en konfigureret LoginModul, vi kan starte godkendelsesprocessen ved at initialisere en LoginContext objekt:

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

På dette tidspunkt, vi kan påberåbe sig Log på() metode til at godkende brugeren:

loginContext.login ();

Det Log på() metode skaber igen en ny instans af vores LoginModul og kalder det Log på() metode. Og, efter vellykket godkendelse kan vi hente det godkendte Emne:

Emneemne = loginContext.getSubject ();

Lad os nu køre en prøveapplikation, der har LoginModul 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 bliver bedt om at angive brugernavnet og adgangskoden, bruger vi det testbruger og testadgangskode som legitimationsoplysninger.

7. Godkendelse

Autorisation kommer i spil, når brugeren først oprettes forbindelse og tilknyttes AccessControlContext. Ved hjælp af Java-sikkerhedspolitikken kan vi give en eller flere adgangskontrolrettigheder til Rektors. Vi kan derefter forhindre adgang til følsom kode ved at ringe til SecurityManager # checkPermission metode:

SecurityManager.checkPermission (tilladelse perm)

7.1. Definition af tilladelser

En adgangskontrolret eller tilladelse er evnen til at udføre en handling på en ressource. Vi kan implementere en tilladelse ved at underklassificere Tilladelse abstrakt klasse. For at gøre dette er vi nødt til at angive et ressourcenavn og et sæt mulige handlinger. For eksempel kan vi bruge FilePermission for at konfigurere adgangskontrolrettigheder på filer. Mulige handlinger er Læs, skrive, udføre, og så videre. I scenarier, hvor handlinger ikke er nødvendige, kan vi bare bruge BasicPermision.

Dernæst giver vi en implementering af tilladelse gennem ResourcePermission klasse, hvor brugere kan have tilladelse til at få adgang til en ressource:

offentlig endelig klasse ResourcePermission udvider BasicPermission {public ResourcePermission (String name) {super (name); }}

Senere konfigurerer vi en post til denne tilladelse gennem Java-sikkerhedspolitikken.

7.2. Tilladelse

Normalt behøver vi ikke kende syntaks for politikfiler, fordi vi altid kan bruge politikværktøjet til at oprette en. Lad os se på vores politikfil:

tildel hovedstol com.sun.security.auth.UserPrincipal testuser {tilladelse com.baeldung.jaas.ResourcePermission "test_resource"};

I denne prøve vi har givet test_ressource tilladelse til testbruger bruger.

7.3. Kontrol af tilladelser

En gang Emne er godkendt og tilladelser er konfigureret, vi kan tjekke for adgang ved at ringe til Emne # doAs eller Emne # doAsPrivilieged statiske metoder. Til dette formål giver vi en PrivilegedAction hvor vi kan beskytte adgangen til følsom kode. I løb() metode, vi kalder SecurityManager # checkPermission metode til at sikre, at den godkendte bruger har test_ressource tilladelse:

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 adgang til test_resource!"); returnere null; }}

Den sidste ting er at ringe til Emne # doAsPrivileged metode:

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

Ligesom godkendelsen kører vi en simpel ansøgning om godkendelse, hvor der ud over LoginModul, vi leverer en tilladelseskonfigurationsfil:

$ 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. Konklusion

I denne artikel har vi vist, hvordan man implementerer JAAS ved at udforske de vigtigste klasser og grænseflader og vise, hvordan man konfigurerer dem. Især har vi implementeret en tjenesteudbyder LoginModul.

Som sædvanlig er koden i denne artikel tilgængelig på GitHub.

Java bund

Jeg har lige annonceret det nye Lær foråret kursus med fokus på det grundlæggende i Spring 5 og Spring Boot 2:

>> KONTROLLER KURSEN

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