Używam Java 6 i próbuję utworzyć HttpsURLConnection
przeciwko zdalnemu serwerowi, używając certyfikatu klienta.
Serwer używa certyfikatu głównego z podpisem własnym i wymaga przedstawienia certyfikatu klienta chronionego hasłem. Dodałem certyfikat główny serwera i certyfikat klienta do domyślnego magazynu kluczy java, który znalazłem w /System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Home/lib/security/cacerts
(OSX 10.5). Nazwa pliku kluczy wydaje się sugerować, że certyfikat klienta nie powinien tam być umieszczony?
W każdym razie dodanie certyfikatu głównego do tego sklepu rozwiązało niesławny javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed' problem.
Jednak teraz utknąłem na tym, jak używać certyfikatu klienta. Wypróbowałem dwa podejścia i żadne mnie nie prowadzi.
Najpierw i najlepiej spróbuj:
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
URL url = new URL("https://somehost.dk:3049");
HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
conn.setSSLSocketFactory(sslsocketfactory);
InputStream inputstream = conn.getInputStream();
// The last line fails, and gives:
// javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
Próbowałem pominąć klasę HttpsURLConnection (nie jest to idealne rozwiązanie, ponieważ chcę rozmawiać z serwerem HTTP) i zamiast tego robię to:
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("somehost.dk", 3049);
InputStream inputstream = sslsocket.getInputStream();
// do anything with the inputstream results in:
// java.net.SocketTimeoutException: Read timed out
Nie jestem nawet pewien, czy problem dotyczy certyfikatu klienta.
Odpowiedzi:
Wreszcie rozwiązałem;). Dostał silną wskazówkę tutaj (Gandalfs odpowiedź dotknął trochę na nim również). Brakujące linki były (głównie) pierwszym z poniższych parametrów i do pewnego stopnia przeoczyłem różnicę między magazynami kluczy i zaufanymi.
Certyfikat serwera z podpisem własnym należy zaimportować do magazynu zaufanych certyfikatów:
Te właściwości należy ustawić (w wierszu poleceń lub w kodzie):
Działający przykładowy kod:
źródło
Chociaż nie jest to zalecane, możesz też całkowicie wyłączyć sprawdzanie poprawności certyfikatu SSL:
źródło
Czy ustawiłeś właściwości KeyStore i / lub TrustStore System?
lub z kodu
To samo z javax.net.ssl.trustStore
źródło
Jeśli masz do czynienia z wywołaniem usługi sieci Web przy użyciu struktury Axis, istnieje znacznie prostsza odpowiedź. Jeśli chcesz, aby Twój klient mógł wywoływać usługę sieciową SSL i ignorować błędy certyfikatu SSL, po prostu umieść to oświadczenie przed wywołaniem jakichkolwiek usług internetowych:
System.setProperty("axis.socketSecureFactory", "org.apache.axis.components.net.SunFakeTrustSocketFactory");
Obowiązują zwykłe zastrzeżenia dotyczące tego, że jest to bardzo zła rzecz w środowisku produkcyjnym.
Znalazłem to na wiki Axis .
źródło
Dla mnie to działało przy użyciu Apache HttpComponents ~ HttpClient 4.x:
Plik P12 zawiera certyfikat klienta i klucz prywatny klienta, utworzony za pomocą BouncyCastle:
źródło
keyStore
zawiera klucz prywatny i certyfikat.Używam pakietu Apache commons HTTP Client, aby to zrobić w moim obecnym projekcie i działa dobrze z SSL i certyfikatem z podpisem własnym (po zainstalowaniu go w cacerts, jak wspomniałeś). Proszę spojrzeć na to tutaj:
http://hc.apache.org/httpclient-3.x/tutorial.html
http://hc.apache.org/httpclient-3.x/sslguide.html
źródło
SSLContext
bezpośrednio, więc możesz skonfigurować to wszystko w ten sposób, zamiast używaćAuthSSLProtocolSocketFactory
.Myślę, że masz problem z certyfikatem serwera, nie jest to ważny certyfikat (myślę, że to właśnie oznacza w tym przypadku „handshake_failure”):
Zaimportuj certyfikat serwera do magazynu kluczy trustcacerts w środowisku JRE klienta. Można to łatwo zrobić za pomocą narzędzia keytool :
źródło
Używając poniższego kodu
lub
wcale nie jest wymagane. Nie ma również potrzeby tworzenia własnej niestandardowej fabryki SSL.
Napotkałem również ten sam problem, w moim przypadku był problem polegający na tym, że cały łańcuch certyfikatów nie został zaimportowany do zaufanych magazynów. Importuj certyfikaty za pomocą narzędzia keytool bezpośrednio z certyfikatu głównego, a także możesz otworzyć plik cacerts w notatniku i sprawdzić, czy cały łańcuch certyfikatów został zaimportowany, czy nie. Sprawdź nazwę aliasu, którą podałeś podczas importu certyfikatów, otwórz certyfikaty i zobacz, ile zawiera, taka sama liczba certyfikatów powinna znajdować się w pliku cacerts.
Również plik cacerts powinien być skonfigurowany na serwerze, na którym uruchamiasz swoją aplikację, oba serwery będą się wzajemnie uwierzytelniać za pomocą kluczy publicznych / prywatnych.
źródło