Een inleiding tot Java SASL

Java Top

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS

1. Overzicht

In deze zelfstudie bespreken we de basisprincipes van Simple Authentication and Security Layer (SASL). We zullen begrijpen hoe Java het gebruik van SASL ondersteunt voor het beveiligen van communicatie.

Tijdens het proces zullen we eenvoudige client- en servercommunicatie gebruiken en deze beveiligen met SASL.

2. Wat is SASL?

SASL is een raamwerk voor authenticatie en gegevensbeveiliging in internetprotocollen. Het heeft tot doel internetprotocollen los te koppelen van specifieke authenticatiemechanismen. We zullen delen van deze definitie beter begrijpen terwijl we verder gaan.

De behoefte aan beveiliging in communicatie is impliciet. Laten we proberen begrijp dit in de context van client- en servercommunicatie. Meestal wisselen client en server gegevens uit via het netwerk. Het is absoluut noodzakelijk dat beide partijen elkaar kunnen vertrouwen en gegevens veilig kunnen verzenden.

2.1. Waar doet SASL Passen?

In een applicatie kunnen we SMTP gebruiken om e-mails te verzenden en LDAP gebruiken om toegang te krijgen tot directoryservices. Maar elk van deze protocollen ondersteunt mogelijk een ander authenticatiemechanisme, zoals Digest-MD5 of Kerberos.

Wat als er een manier was voor protocollen om authenticatiemechanismen meer declaratief uit te wisselen? Dit is precies waar SASL in beeld komt. Protocollen die SASL ondersteunen, kunnen steevast alle SASL-mechanismen ondersteunen.

Vandaar, applicaties kunnen onderhandelen over een geschikt mechanisme en pas dat toe voor authenticatie en veilige communicatie.

2.2. Hoe werkt SASL Werk?

Nu we hebben gezien waar SASL in het algemene beveiligingsschema past, laten we eens kijken hoe het werkt.

SASL is een challenge-response-raamwerk. Hier geeft de server een uitdaging aan de klant, en de klant stuurt een antwoord op basis van de uitdaging. De uitdaging en het antwoord zijn byte-arrays van willekeurige lengte en kunnen daarom alle mechanismespecifieke gegevens bevatten.

Dit uitwisseling kan doorgaan voor meerdere iteraties en eindigt uiteindelijk wanneer de server geen verdere uitdaging meer geeft.

Bovendien kunnen de client en server na authenticatie onderhandelen over een beveiligingslaag. Alle volgende communicatie kan dan gebruikmaken van deze beveiligingslaag. Houd er echter rekening mee dat sommige mechanismen mogelijk alleen authenticatie ondersteunen.

Het is belangrijk om hier te begrijpen dat SASL biedt alleen een kader voor de uitwisseling van uitdaging en reactie gegevens. Het vermeldt niets over de gegevens zelf of hoe ze worden uitgewisseld. Die details worden overgelaten aan de toepassingen die SASL gebruiken.

3. SASL-ondersteuning in Java

Er zijn API's in Java die ondersteuning voor het ontwikkelen van zowel client-side als servertoepassingen met SASL. De API is niet afhankelijk van de feitelijke mechanismen zelf. Toepassingen die Java SASL API gebruiken, kunnen een mechanisme selecteren op basis van vereiste beveiligingsfuncties.

3.1. Java SASL API

De belangrijkste interfaces om op te merken, als onderdeel van het pakket "javax.security.sasl", zijn SaslServer en SaslClient.

SaslServer vertegenwoordigt het server-side mechanisme van SASL.

Laten we eens kijken hoe we een SaslServer:

SaslServer ss = Sasl.createSaslServer (mechanisme, protocol, servernaam, rekwisieten, callbackHandler);

We gebruiken de fabrieksklasse Sasl instantiëren SaslServer. De methode createSaslServer accepteert verschillende parameters:

  • mechanisme - de IANA geregistreerde naam van een door SASL ondersteund mechanisme
  • protocol - de naam van het protocol waarvoor authenticatie plaatsvindt
  • server naam - de volledig gekwalificeerde hostnaam van de server
  • rekwisieten - een reeks eigenschappen die worden gebruikt om de authenticatie-uitwisseling te configureren
  • callbackHandler - een callback-handler die door het geselecteerde mechanisme moet worden gebruikt om meer informatie te krijgen

Van het bovenstaande zijn alleen de eerste twee verplicht, en de rest is nul.

SaslClient vertegenwoordigt het client-side mechanisme van SASL. Laten we eens kijken hoe we een SaslClient:

SaslClient sc = Sasl.createSaslClient (mechanismen, autorisatie-id, protocol, servernaam, rekwisieten, callbackHandler);

Ook hier gebruiken we de fabrieksklasse Sasl om onze SaslClient. De lijst met parameters die createSaslClient accepteert is vrijwel hetzelfde als voorheen.

Er zijn echter enkele subtiele verschillen:

  • mechanismen - hier is dit een lijst met mechanismen om uit te proberen
  • autorisatie-id - dit is een protocolafhankelijke identificatie die moet worden gebruikt voor autorisatie

De rest van de parameters hebben dezelfde betekenis en hun optionaliteit.

3.2. Java SASL-beveiligingsprovider

Onder de Java SASL API bevinden zich de feitelijke mechanismen die de beveiligingsfuncties bieden. De implementatie van deze mechanismen wordt verzorgd door beveiligingsproviders geregistreerd bij de Java Cryptography Architecture (JCA).

Er kunnen meerdere beveiligingsproviders zijn geregistreerd bij de JCA. Elk van deze kan een of meer van de SASL-mechanismen ondersteunen.

Java wordt geleverd met SunSASL als beveiligingsprovider, die standaard wordt geregistreerd als JCA-provider. Dit kan echter worden verwijderd of opnieuw worden gerangschikt bij andere beschikbare providers.

Bovendien is het altijd mogelijk om een ​​aangepaste beveiligingsprovider te bieden. Dit vereist dat we de interfaces implementeren SaslClient en SaslServer. Daarbij kunnen we ook ons ​​aangepaste beveiligingsmechanisme implementeren!

4. SASL door middel van een voorbeeld

Nu we hebben gezien hoe u een SaslServer en een SaslClient, is het tijd om te begrijpen hoe u ze moet gebruiken. We gaan client- en servercomponenten ontwikkelen. Deze zullen iteratief uitdaging en respons uitwisselen om authenticatie te bereiken. We zullen het DIGEST-MD5-mechanisme gebruiken in ons eenvoudige voorbeeld hier.

4.1. Client en server CallbackHandler

Zoals we eerder zagen, moeten we implementaties van CallbackHandler naar SaslServer en SaslClient. Nu, CallbackHandler is een eenvoudige interface die een enkele methode definieert - handvat. Deze methode accepteert een array van Bel terug.

Hier, Bel terug biedt een manier voor het beveiligingsmechanisme om authenticatiegegevens van de aanroepende applicatie te verzamelen. Een beveiligingsmechanisme kan bijvoorbeeld een gebruikersnaam en wachtwoord vereisen. Er zijn er nogal wat Bel terug implementaties zoals Naam Terugbellen en Wachtwoord Terugbellen beschikbaar voor gebruik.

Laten we eens kijken hoe we een CallbackHandler voor de server, om te beginnen:

public class ServerCallbackHandler implementeert CallbackHandler {@Override public void handle (Callback [] cbs) gooit IOException, UnsupportedCallbackException {voor (Callback cb: cbs) {if (cb instantie van AuthorizeCallback) {AuthorizeCallback ac = (AuthorizeCallback) cb; // Voer applicatiespecifieke autorisatieactie uit ac.setAuthorized (true); } else if (cb instantie van NameCallback) {NameCallback nc = (NameCallback) cb; // Verzamel gebruikersnaam op applicatiespecifieke manier nc.setName ("gebruikersnaam"); } else if (cb instantie van PasswordCallback) {PasswordCallback pc = (PasswordCallback) cb; // Verzamel wachtwoord op applicatiespecifieke manier pc.setPassword ("wachtwoord" .toCharArray ()); } else if (cb instantie van RealmCallback) {RealmCallback rc = (RealmCallback) cb; // Verzamel realm-gegevens op applicatiespecifieke manier rc.setText ("myServer"); }}}}

Laten we nu eens kijken naar onze klantzijde van het Callbackhandler:

public class ClientCallbackHandler implementeert CallbackHandler {@Override public void handle (Callback [] cbs) gooit IOException, UnsupportedCallbackException {voor (Callback cb: cbs) {if (cb instantie van NameCallback) {NameCallback nc = (NameCallback) cb; // Verzamel gebruikersnaam op applicatiespecifieke manier nc.setName ("gebruikersnaam"); } else if (cb instantie van PasswordCallback) {PasswordCallback pc = (PasswordCallback) cb; // Verzamel wachtwoord op applicatiespecifieke manier pc.setPassword ("wachtwoord" .toCharArray ()); } else if (cb instantie van RealmCallback) {RealmCallback rc = (RealmCallback) cb; // Verzamel realm-gegevens op applicatiespecifieke manier rc.setText ("myServer"); }}}}

Voor alle duidelijkheid: we zijn doorlopend door de Bel terug array en het afhandelen van alleen specifieke. Degenen die we moeten afhandelen, zijn specifiek voor het gebruikte mechanisme, dat hier DIGEST-MD5 is.

4.2. SASL-verificatie

Dus we hebben onze client en server geschreven CallbackHandler. We hebben ook geïnstantieerd SaslClient en SaslServer voor DIGEST-MD5-mechanisme.

Dit is het moment om ze in actie te zien:

@Test openbare ongeldig gegevenHandlers_whenStarted_thenAutenticationWorks () gooit SaslException {byte [] uitdaging; byte [] antwoord; challenge = saslServer.evaluateResponse (nieuwe byte [0]); response = saslClient.evaluateChallenge (uitdaging); challenge = saslServer.evaluateResponse (antwoord); response = saslClient.evaluateChallenge (uitdaging); assertTrue (saslServer.isComplete ()); assertTrue (saslClient.isComplete ()); }

Laten we proberen te begrijpen wat hier gebeurt:

  • Ten eerste krijgt onze klant de standaarduitdaging van de server
  • De klant evalueert vervolgens de uitdaging en bereidt een antwoord voor
  • Deze uitwisseling tussen uitdaging en reactie duurt nog een cyclus
  • Tijdens het proces maken de client en de server gebruik van callback-handlers om eventuele aanvullende gegevens te verzamelen die het mechanisme nodig heeft
  • Hiermee is onze authenticatie hier afgerond, maar in werkelijkheid kan het zich herhalen over meerdere cycli

EEN typische uitwisseling van challenge- en responsbyte-arrays vindt plaats via het netwerk. Maar hier voor de eenvoud zijn we uitgegaan van lokale communicatie.

4.3. SASL beveiligde communicatie

Zoals we eerder hebben besproken, is SASL een raamwerk dat in staat is om veilige communicatie te ondersteunen die verder gaat dan alleen authenticatie. Echter, dit is alleen mogelijk als het onderliggende mechanisme dit ondersteunt.

Laten we eerst eens kijken of we hebben kunnen onderhandelen over een veilige communicatie:

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

Hier, QOP staat voor de kwaliteit van bescherming. Dit is iets waarover de client en server onderhandelen tijdens authenticatie. De waarde "auth-int" geeft authenticatie en integriteit aan. Terwijl de waarde van "auth-conf" duidt op authenticatie, integriteit en vertrouwelijkheid.

Zodra we een beveiligingslaag hebben, kunnen we die gebruiken om onze communicatie te beveiligen.

Laten we eens kijken hoe we uitgaande communicatie in de klant kunnen beveiligen:

byte [] outgoing = "Baeldung" .getBytes (); byte [] secureOutgoing = saslClient.wrap (uitgaand, 0, uitgaand.lengte); // Verzend secureOutgoing via het netwerk naar de server

En op dezelfde manier kan de server inkomende communicatie verwerken:

// Ontvang secureIncoming van de client via de netwerkbyte [] incoming = saslServer.unwrap (secureIncoming, 0, netIn.length); assertEquals ("Baeldung", nieuwe String (inkomend, StandardCharsets.UTF_8));

5. SASL in de echte wereld

We hebben nu dus een goed begrip van wat SASL is en hoe we het in Java kunnen gebruiken. Maar meestal is dat niet waarvoor we SASL gaan gebruiken, althans in onze dagelijkse routine.

Zoals we eerder zagen, SASL is primair bedoeld voor protocollen als LDAP en SMTP. Hoewel er steeds meer applicaties en aan boord komen met SASL - bijvoorbeeld Kafka. Dus, hoe gebruiken we SASL om te authenticeren met dergelijke services?

Stel dat we Kafka Broker voor SASL hebben geconfigureerd met PLAIN als het voorkeursmechanisme. PLAIN betekent simpelweg dat het authenticeert met een combinatie van gebruikersnaam en wachtwoord in platte tekst.

Laten we nu eens kijken hoe we een Java-client kunnen configureren om SASL / PLAIN te gebruiken voor authenticatie tegen de Kafka Broker.

We beginnen met het verstrekken van een eenvoudige JAAS-configuratie, "kafka_jaas.conf":

KafkaClient {org.apache.kafka.common.security.plain.PlainLoginModule vereiste gebruikersnaam = "gebruikersnaam" wachtwoord = "wachtwoord"; };

We maken gebruik van deze JAAS-configuratie bij het starten van de JVM:

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

Ten slotte moeten we een paar eigenschappen toevoegen om door te geven aan onze producenten- en consumenteninstanties:

security.protocol = SASL_SSL sasl.mechanism = PLAIN

Dat is alles wat er is. Dit is echter slechts een klein deel van de Kafka-clientconfiguraties. Behalve PLAIN ondersteunt Kafka ook GSSAPI / Kerberos voor authenticatie.

6. SASL in vergelijking

Hoewel SASL behoorlijk effectief is in het bieden van een mechanisme-neutrale manier voor het verifiëren en beveiligen van client- en servercommunicatie. Echter, SASL is niet de enige beschikbare oplossing in dit verband.

Java biedt zelf andere mechanismen om dit doel te bereiken. We zullen ze kort bespreken en begrijpen hoe ze het doen tegen SASL:

  • Java Secure Socket Extension (JSSE): JSSE is een set pakketten in Java die Secure Sockets Layer (SSL) voor Java implementeert. Het biedt gegevenscodering, client- en serververificatie en berichtintegriteit. In tegenstelling tot SASL vertrouwt JSSE op een Public Key Infrastructure (PKI) om te werken. Daarom is SASL flexibeler en lichter dan JSSE.
  • Java GSS API (JGSS): JGGS is de Java-taalbinding voor Generic Security Service Application Programming Interface (GSS-API). GSS-API is een IETF-standaard voor applicaties om toegang te krijgen tot beveiligingsdiensten. In Java, onder GSS-API, is Kerberos het enige ondersteunde mechanisme. Kerberos vereist opnieuw een Kerberized-infrastructuur om te werken. In vergelijking met SASL zijn de keuzes hier nog beperkt en zwaar.

Over het algemeen is SASL een zeer lichtgewicht framework en biedt het een breed scala aan beveiligingsfuncties via insteekbare mechanismen. Toepassingen die SASL gebruiken, hebben veel keuzes bij het implementeren van de juiste set beveiligingsfuncties, afhankelijk van de behoefte.

7. Conclusie

Samenvattend, in deze tutorial hebben we de basisprincipes van het SASL-framework begrepen, dat authenticatie en veilige communicatie biedt. We bespraken ook de API's die in Java beschikbaar zijn voor het implementeren van de client- en server-side van SASL.

We hebben gezien hoe we een beveiligingsmechanisme kunnen gebruiken via een JCA-provider. Ten slotte hebben we het ook gehad over het gebruik van SASL bij het werken met verschillende protocollen en applicaties.

Zoals altijd is de code te vinden op GitHub.

Java onderkant

Ik heb zojuist het nieuwe aangekondigd Leer de lente natuurlijk, gericht op de basisprincipes van Spring 5 en Spring Boot 2:

>> BEKIJK DE CURSUS