IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Lekce 17 - HTTPS v Javě

V minulé lekci, Knihovna Jsoup v Javě - Pokročilé vyhledávání, jsme si ukázali, jak lze pracovat například s obrázky, odkazy či atributy v html dokumentu pomocí Java knihovny Jsoup.

V tomto článku si ukážeme, jak funguje ověřování serverových SSL/TLS certifikátů a kde jsou uloženy certifikáty důvěryhodných autorit.

Načtení dat z protokolu HTTPS

K práci s protokolem HTTPS (Hypertext Transfer Protocol Secure) lze podobně jako v případě HTTP použít třídy z balíku java.net. Potřebujeme-li například z nějakého serveru stáhnout webovou stránku přes HTTPS, stačí vytvořit objekt java.net.URL s požadovanou adresou, otevřít spojení a z příslušného objektu InputStream přečíst data:

String address = "https://www.google.com";
URL url = new URL(address);
URLConnection connection = url.openConnection();
InputStream in = null;
ByteArrayOutputStream out = new ByteArrayOutputStream();
try {
    in = connection.getInputStream();
    byte[] buffer = new byte[8192];
    int size;
    while ((size = in.read(buffer)) != -1) {
        out.write(buffer, 0, size);
    }
} finally {
    if (in != null) {
        in.close();
    }
}
String content = out.toString("UTF-8");

Kód výše funguje za předpokladu, že je HTTPS server resp. jeho certifikát považován za důvěryhodný. Není-li tomu tak, spojení selže a dojde k vyhození výjimky javax.net.ssl.SSLHandshakeException:

javax.net.ssl.SSLHandshakeException:
sun.security.validator.ValidatorException:
PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target

Podívejme se tedy blíže na serverové SSL/TLS certifikáty, kde jsou uloženy certifikáty důvěryhodných autorit a na možnosti ošetření této výjimky.

Certifikační cesta

Aby byl certifikát serveru považován za důvěryhodný, musí být vydán důvěryhodnou certifikační autoritou. Certifikát certifikační autority vydává buď certifikační autorita sama, v tomto případě se jedná o kořenovou certifikační autoritu, nebo její nadřízená certifikační autorita.

Certifikáty tvoří tzv. řetězec (chain) resp. certifikační cestu (certification path), kde na jednom konci stojí certifikát kořenové certifikační autority, na druhém konci certifikát serveru a mezi nimi se nachází libovolný počet certifikátů podřízených certifikačních autorit.

Truststore

Certifikáty důvěryhodných certifikačních autorit jsou v Javě uloženy v úložišti důvěryhodných certifikátů, v tzv. truststore.

Výchozím úložištěm důvěryhodných certifikátů je soubor cacerts v adresáři C:\Program Files\Java\jre7\lib\security. Umístění adresáře se může lišit podle verze JRE. Certifikáty jsou uloženy ve formátu JKS (Java KeyStore) a chráněny heslem. Výchozí heslo zní changeit.

Úložiště lze spravovat pomocí nástroje keytool, který je součástí Java SE Development Kit. Například obsah lze vypsat příkazem:

keytool -list -storepass changeit -keystore "C:\Program Files\Java\jre7\lib\security\cacerts"

Popis všech parametrů nástroje keytool je k dispozici na stránkách Oracle.

Umístění úložiště důvěryhodných certifikátů lze pro daný proces změnit pomocí argumentu JVM javax.net.ssl.trustStore. Argumentem javax.net.ssl.trustStorePassword lze specifikovat heslo.

Podívejme se na příklad spuštění aplikace s vlastním úložištěm důvěryhodných certifikátů:

java -Djavax.net.ssl.trustStore=mujtruststore.jks -Djavax.net.ssl.trustStorePassword=supertajneheslo -jar moje-aplikace.jar

Trust manager

Někdy je potřeba mít nad ověřováním SSL/TLS certifikátů větší kontrolu. Představme si například, že naše aplikace komunikuje s aplikacemi našich obchodních partnerů. Každý partner má vlastní server s vlastním SSL certifikátem. A naše aplikace potřebuje ověřit, že certifikát serveru přísluší danému partnerovi.

Dalším příkladem je situace, kdy nechceme vůbec používat file system, ale certifikáty spravujeme v rámci naší aplikace, uložené např. v databázi. Nebo si představme případ, kdy certifikáty nechceme ověřovat vůbec.

Pro všechny tyto případy můžeme použít vlastní implementaci rozhraní javax.net.ssl.X509TrustManager. Ověření certifikátů serveru se děje v metodě checkServerTrusted. Metoda vyhazuje výjimku CertificateException, pokud ověření selže a certifikát není považován za důvěryhodný.

Takto lze vytvořit náš vlastní trust manager, který akceptuje libovolný certifikát serveru:

public class MyTrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        throw new CertificateException();
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
        /* Ověřit řetězec certifikátů */
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return new X509Certificate[0];
    }

}

Následující kód pro dané HTTPS spojení nastaví náš trust manager. Trust manager je ukrytý v objektu třídy SSLSocketFactory, který nejprve vytvoříme pomocí třídy SSLContext. Objekt SSLSocketFactory nastavíme pro dané připojení metodou setSSLSocketFactory rozhraní HttpsURLConnection:

MyTrustManager trustManager = new MyTrustManager();
TrustManager[] tm = { trustManager };
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tm, null);
SSLSocketFactory socketFactory = context.getSocketFactory();

String address = "https://localhost";
URL url = new URL(address);
URLConnection connection = url.openConnection();
if (connection instanceof HttpsURLConnection) {
    ((HttpsURLConnection) connection).setSSLSocketFactory(socketFactory);
}

Alternativně lze pomocí metody SSLContext.setDefault nastavit SSL kontext s vlastním trust managerem globálně pro celou aplikaci.

Možnosti řešení SSLHandshakeException

Co tedy dělat, pokud v naší aplikaci dochází k SSLHandshakeException při pokusu o připojení k serveru přes HTTPS?

Možnosti máme tyto:

  1. Přidat certifikát serveru resp. certifikát certifikační autority do výchozího úložiště důvěryhodných certifikátů do souboru cacerts.
  2. Uložit certifikát do vlastního úložiště a spustit aplikaci s argumenty JVM javax.net.ssl.trustStore a javax.net.ssl.trustStorePassword.
  3. Použít vlastní implementaci X509TrustManager.

V příští lekci, Síť v Javě - Práce s cookies, si vysvětlíme, jak fungují cookies a k čemu slouží. Naučíme se je také vytvořit a číst a popíšeme si jejich atributy.


 

Předchozí článek
Knihovna Jsoup v Javě - Pokročilé vyhledávání
Všechny články v sekci
Síť v Javě
Přeskočit článek
(nedoporučujeme)
Síť v Javě - Práce s cookies
Článek pro vás napsal Silvinios
Avatar
Uživatelské hodnocení:
5 hlasů
Aktivity