En introduktion til Java SASL

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

I denne vejledning gennemgår vi det grundlæggende i Simple Authentication and Security Layer (SASL). Vi forstår, hvordan Java understøtter vedtagelse af SASL til sikring af kommunikation.

I processen bruger vi simpel klient- og serverkommunikation og sikrer den med SASL.

2. Hvad er? SASL?

SASL er en ramme for godkendelse og datasikkerhed i internetprotokoller. Det sigter mod at afkoble internetprotokoller fra specifikke godkendelsesmekanismer. Vi forstår bedre dele af denne definition, når vi går videre.

Behovet for sikkerhed i kommunikationen er implicit. Lad os prøve at forstå dette i sammenhæng med klient- og serverkommunikation. Typisk udveksler klient og server data over netværket. Det er bydende nødvendigt, at begge parter kan stole på hinanden og sende data sikkert.

2.1. Hvor gør SASL Passe ind?

I en applikation bruger vi muligvis SMTP til at sende e-mails og bruge LDAP til at få adgang til bibliotekstjenester. Men hver af disse protokoller understøtter muligvis en anden godkendelsesmekanisme, som Digest-MD5 eller Kerberos.

Hvad hvis der var en måde for protokoller at bytte godkendelsesmekanismer mere erklærende på? Det er her SASL kommer ind i billedet. Protokoller, der understøtter SASL, kan altid understøtte enhver af SASL-mekanismerne.

Derfor, applikationer kan forhandle om en passende mekanisme og vedtag det til godkendelse og sikker kommunikation.

2.2. Hvordan gør SASL Arbejde?

Nu, hvor vi har set, hvor SASL passer ind i den overordnede sikkerhedsplan, lad os forstå, hvordan det fungerer.

SASL er en udfordrings-reaktionsramme. Her udsteder serveren en udfordring til klienten, og klienten sender et svar baseret på udfordringen. Udfordringen og svaret er byte-arrays med vilkårlig længde og kan derfor bære enhver mekanismespecifik data.

Det her udveksling kan fortsætte med flere gentagelser og slutter til sidst, når serveren ikke udsteder yderligere udfordringer.

Desuden kan klienten og serveren forhandle om et sikkerhedslag efter godkendelse. Al efterfølgende kommunikation kan derefter udnytte dette sikkerhedslag. Bemærk dog, at nogle af mekanismerne muligvis kun understøtter godkendelse.

Det er vigtigt at forstå her, at SASL giver kun en ramme for udveksling af udfordringer og svar data. Det nævner ikke noget om selve dataene eller hvordan de udveksles. Disse detaljer er tilbage til applikationerne, der vedtager at bruge SASL.

3. SASL-support i Java

Der er API'er i Java, der understøtter udvikling af både klientsiden og serversiden med SASL. API'en er ikke afhængig af selve mekanismerne. Applikationer, der bruger Java SASL API, kan vælge en mekanisme baseret på de nødvendige sikkerhedsfunktioner.

3.1. Java SASL API

De vigtigste grænseflader, der skal bemærkes, som en del af pakken “javax.security.sasl” er SaslServer og SaslClient.

SaslServer repræsenterer SASL-serverens mekanisme.

Lad os se, hvordan vi kan instantiere en SaslServer:

SaslServer ss = Sasl.createSaslServer (mekanisme, protokol, servernavn, rekvisitter, callbackHandler);

Vi bruger fabriksklassen Sasl at instantiere SaslServer. Metoden createSaslServer accepterer flere parametre:

  • mekanisme - det IANA-registrerede navn på en SASL-understøttet mekanisme
  • protokol - navnet på den protokol, som godkendelsen udføres for
  • server navn - det fuldt kvalificerede værtsnavn på serveren
  • rekvisitter - et sæt egenskaber, der bruges til at konfigurere godkendelsesudvekslingen
  • callbackHandler - en tilbagekaldshåndterer, der skal bruges af den valgte mekanisme til at få yderligere information

Ud af ovenstående er kun de to første obligatoriske, og resten er ugyldige.

SaslClient repræsenterer klientsidemekanismen for SASL. Lad os se, hvordan kan vi instantiere en SaslClient:

SaslClient sc = Sasl.createSaslClient (mekanismer, autorisations-id, protokol, servernavn, rekvisitter, callbackHandler);

Her bruger vi igen fabriksklassen Sasl at instantiere vores SaslClient. Listen over parametre, som createSaslClient accepterer er stort set det samme som før.

Der er dog nogle subtile forskelle:

  • mekanismer - her er dette en liste over mekanismer, du kan prøve
  • autorisations-id - dette er en protokolafhængig identifikation, der skal bruges til godkendelse

Resten af ​​parametrene er ens i betydning og deres valgfrihed.

3.2. Java SASL-sikkerhedsudbyder

Under Java SASL API er de faktiske mekanismer, der giver sikkerhedsfunktionerne. Det implementering af disse mekanismer leveres af sikkerhedsudbydere registreret med Java Cryptography Architecture (JCA).

Der kan være flere sikkerhedsudbydere registreret hos JCA. Hver af disse understøtter muligvis en eller flere af SASL-mekanismerne.

Java leveres med SunSASL som en sikkerhedsudbyder, der som standard bliver registreret som en JCA-udbyder. Dette kan dog fjernes eller genbestilles med andre tilgængelige udbydere.

Desuden er det altid muligt at levere en brugerdefineret sikkerhedsudbyder. Dette kræver, at vi implementerer grænsefladerne SaslClient og SaslServer. Dermed implementerer vi muligvis også vores brugerdefinerede sikkerhedsmekanisme!

4. SASL gennem et eksempel

Nu hvor vi har set hvordan man opretter en SaslServer og en SaslClient, det er tid til at forstå, hvordan man bruger dem. Vi udvikler klient- og serverkomponenter. Disse udveksler udfordring og respons iterativt for at opnå godkendelse. Vi bruger DIGEST-MD5-mekanismen i vores enkle eksempel her.

4.1. Klient og server CallbackHandler

Som vi så tidligere, er vi nødt til at levere implementeringer af CallbackHandler til SaslServer og SaslClient. Nu, CallbackHandler er en simpel grænseflade, der definerer en enkelt metode - håndtere. Denne metode accepterer en række Ring tilbage.

Her, Ring tilbage præsenterer en måde, hvorpå sikkerhedsmekanismen kan indsamle godkendelsesdata fra opkaldsprogrammet. For eksempel kan en sikkerhedsmekanisme kræve et brugernavn og en adgangskode. Der er en hel del Ring tilbage implementeringer som NameCallback og PasswordCallback tilgængelig til brug.

Lad os se, hvordan vi kan definere en CallbackHandler til serveren, til at begynde med:

offentlig klasse ServerCallbackHandler implementerer CallbackHandler {@Override public void handle (Callback [] cbs) kaster IOException, UupportedCallbackException {for (Callback cb: cbs) {if (cb instanceof AuthorizeCallback) {AuthorizeCallback ac = (AuthorizeCallback) cb; // Udfør applikationsspecifik autorisationshandling ac.setAuthorized (true); } ellers hvis (cb forekomst af NameCallback) {NameCallback nc = (NameCallback) cb; // Saml brugernavn på applikationsspecifik måde nc.setName ("brugernavn"); } ellers hvis (cb forekomst af PasswordCallback) {PasswordCallback pc = (PasswordCallback) cb; // Saml adgangskode på applikationsspecifik måde pc.setPassword ("adgangskode" .toCharArray ()); } ellers hvis (cb forekomst af RealmCallback) {RealmCallback rc = (RealmCallback) cb; // Saml rigsdata på applikationsspecifik måde rc.setText ("myServer"); }}}}

Lad os nu se vores klientside af Tilbagekaldshåndterer:

offentlig klasse ClientCallbackHandler implementerer CallbackHandler {@Override public void handle (Callback [] cbs) kaster IOException, UnsupportedCallbackException {for (Callback cb: cbs) {if (cb instanceof NameCallback) {NameCallback nc = (NameCallback) cb; // Saml brugernavn på applikationsspecifik måde nc.setName ("brugernavn"); } ellers hvis (cb forekomst af PasswordCallback) {PasswordCallback pc = (PasswordCallback) cb; // Saml adgangskode på applikationsspecifik måde pc.setPassword ("adgangskode" .toCharArray ()); } ellers hvis (cb forekomst af RealmCallback) {RealmCallback rc = (RealmCallback) cb; // Saml rigsdata på applikationsspecifik måde rc.setText ("myServer"); }}}}

For at afklare er vi løber gennem Ring tilbage array og kun håndtering af specifikke. Dem, som vi skal håndtere, er specifikke for den mekanisme, der er i brug, som er DIGEST-MD5 her.

4.2. SASL-godkendelse

Så vi har skrevet vores klient og server CallbackHandler. Vi har også instantificeret SaslClient og SaslServer til DIGEST-MD5 mekanisme.

Nu er det tid til at se dem i aktion:

@Test offentlig ugyldighed givenHandlers_whenStarted_thenAutenticationWorks () kaster SaslException {byte [] udfordring; svar fra byte []; udfordring = saslServer.evaluateResponse (ny byte [0]); respons = saslClient.evaluateChallenge (udfordring); udfordring = saslServer.evaluateResponse (svar); respons = saslClient.evaluateChallenge (udfordring); assertTrue (saslServer.isComplete ()); assertTrue (saslClient.isComplete ()); }

Lad os prøve at forstå, hvad der sker her:

  • For det første får vores klient standardudfordringen fra serveren
  • Klienten evaluerer derefter udfordringen og forbereder et svar
  • Denne udfordring-svar-udveksling fortsætter i endnu en cyklus
  • I processen bruger klienten og serveren tilbagekaldshåndterere til at indsamle eventuelle yderligere data efter behov af mekanismen
  • Dette afslutter vores godkendelse her, men i virkeligheden kan den gentage sig over flere cyklusser

EN typisk udveksling af udfordrings- og responsbyte-arrays sker over netværket. Men her for enkelheds skyld har vi antaget lokal kommunikation.

4.3. SASL sikker kommunikation

Som vi diskuterede tidligere er SASL en ramme, der er i stand til at understøtte sikker kommunikation ud over blot godkendelse. Imidlertid, dette er kun muligt, hvis den underliggende mekanisme understøtter det.

Lad os først kontrollere, om vi har været i stand til at forhandle om en sikker kommunikation:

String qop = (String) saslClient.getNegotiatedProperty (Sasl.QOP); assertEquals ("auth-conf", qop);

Her, QOP står for kvaliteten af ​​beskyttelsen. Dette er noget, som klienten og serveren forhandler under godkendelse. En værdi af "auth-int" angiver godkendelse og integritet. Mens en værdi af "auth-conf" angiver godkendelse, integritet og fortrolighed.

Når vi først har et sikkerhedslag, kan vi udnytte det for at sikre vores kommunikation.

Lad os se, hvordan vi kan sikre udgående kommunikation i klienten:

byte [] udgående = "Baeldung" .getBytes (); byte [] secureOutgoing = saslClient.wrap (udgående, 0, udgående.længde); // Send sikker udgående til serveren via netværket

Og på samme måde kan serveren behandle indgående kommunikation:

// Modtag sikker indgående fra klienten via netværksbyte [] indkommende = saslServer.unwrap (sikker indgående, 0, netIn.length); assertEquals ("Baeldung", ny streng (indkommende, StandardCharsets.UTF_8));

5. SASL i den virkelige verden

Så vi har nu en god forståelse af, hvad SASL er, og hvordan vi bruger det i Java. Men det er typisk ikke det, vi ender med at bruge SASL til, i det mindste i vores daglige rutine.

Som vi så tidligere, SASL er primært beregnet til protokoller som LDAP og SMTP. Skønt flere og flere applikationer og kommer om bord med SASL - for eksempel Kafka. Så hvordan bruger vi SASL til at godkende med sådanne tjenester?

Lad os antage, at vi har konfigureret Kafka Broker til SASL med PLAIN som den valgte mekanisme. PLAIN betyder simpelthen, at den godkendes ved hjælp af en kombination af brugernavn og adgangskode i almindelig tekst.

Lad os nu se, hvordan vi kan konfigurere en Java-klient til at bruge SASL / PLAIN til at godkende mod Kafka Broker.

Vi begynder med at levere en simpel JAAS-konfiguration, “kafka_jaas.conf”:

KafkaClient {org.apache.kafka.common.security.plain.PlainLoginModule krævede brugernavn = "brugernavn" adgangskode = "adgangskode"; };

Vi bruger denne JAAS-konfiguration, mens vi starter JVM:

-Djava.security.auth.login.config = kafka_jaas.conf

Endelig er vi nødt til at tilføje et par egenskaber, der skal overføres til vores producent- og forbrugerinstanser:

security.protocol = SASL_SSL sasl.mechanism = RET

Det er alt der er ved det. Dette er dog kun en lille del af Kafka-klientkonfigurationer. Bortset fra PLAIN understøtter Kafka også GSSAPI / Kerberos til godkendelse.

6. SASL i sammenligning

Selvom SASL er ret effektiv til at levere en mekanisme-neutral måde at autentificere og sikre klient- og serverkommunikation på. Imidlertid, SASL er ikke den eneste tilgængelige løsning i denne henseende.

Java giver selv andre mekanismer til at nå dette mål. Vi vil kort diskutere dem og forstå, hvordan de klarer sig mod SASL:

  • Java Secure Socket Extension (JSSE): JSSE er et sæt pakker i Java, der implementerer Secure Sockets Layer (SSL) til Java. Det giver datakryptering, klient- og servergodkendelse og beskedintegritet. I modsætning til SASL er JSSE afhængig af en PKI (Public Key Infrastructure) til at arbejde. Derfor fungerer SASL for at være mere fleksibel og let end JSSE.
  • Java GSS API (JGSS): JGGS er Java-sprogbindingen til Generic Security Service Application Programming Interface (GSS-API). GSS-API er en IETF-standard for applikationer, der har adgang til sikkerhedstjenester. I Java, under GSS-API, er Kerberos den eneste understøttede mekanisme. Kerberos kræver igen en Kerberiseret infrastruktur for at fungere. Sammenlignet med SASL er valgmulighederne her endnu begrænsede og tunge.

Samlet set er SASL en meget let ramme og tilbyder en bred vifte af sikkerhedsfunktioner gennem plugbare mekanismer. Applikationer, der vedtager SASL, har mange valgmuligheder i implementeringen af ​​det rigtige sæt sikkerhedsfunktioner afhængigt af behovet.

7. Konklusion

For at opsummere forstod vi i denne vejledning det grundlæggende i SASL-rammen, som giver godkendelse og sikker kommunikation. Vi diskuterede også de tilgængelige API'er i Java til implementering af klient- og serversiden af ​​SASL.

Vi så, hvordan man bruger en sikkerhedsmekanisme gennem en JCA-udbyder. Endelig talte vi også om brugen af ​​SASL til at arbejde med forskellige protokoller og applikationer.

Som altid kan koden findes 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