Un module que je suis en train d'ajouter à notre grande application Java doit converser avec le site Web sécurisé par SSL d'une autre société. Le problème est que le site utilise un certificat auto-signé. Je dispose d'une copie du certificat pour vérifier que je ne suis pas confronté à une attaque de type "man-in-the-middle", et je dois intégrer ce certificat dans notre code de manière à ce que la connexion au serveur soit réussie.
Voici le code de base :
void sendRequest(String dataPacket) {
String urlStr = "https://host.example.com/";
URL url = new URL(urlStr);
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
conn.setMethod("POST");
conn.setRequestProperty("Content-Length", data.length());
conn.setDoOutput(true);
OutputStreamWriter o = new OutputStreamWriter(conn.getOutputStream());
o.write(data);
o.flush();
}
Sans traitement supplémentaire en place pour le certificat auto-signé, il meurt à conn.getOutputStream() avec l'exception suivante :
Exception in thread "main" 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
....
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
....
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
Idéalement, mon code doit apprendre à Java à accepter ce seul certificat auto-signé, pour cet endroit précis de l'application, et nulle part ailleurs.
Je sais que je peux importer le certificat dans le magasin de l'autorité de certification du JRE, ce qui permettra à Java de l'accepter. Ce n'est pas une approche que je veux adopter si je peux l'aider ; cela semble très invasif à faire sur toutes les machines de nos clients pour un module qu'ils n'utilisent peut-être pas ; cela affecterait toutes les autres applications Java utilisant le même JRE, et je n'aime pas cela, même si les chances qu'une autre application Java accède à ce site sont nulles. Ce n'est pas non plus une opération triviale : sous UNIX, je dois obtenir des droits d'accès pour modifier le JRE de cette manière.
J'ai également vu que je pouvais créer une instance de TrustManager qui effectue des contrôles personnalisés. Il semble même que je puisse créer un TrustManager qui délègue au TrustManager réel dans toutes les instances, sauf pour ce certificat. Mais il semble que ce TrustManager soit installé globalement, et je présume qu'il affecterait toutes les autres connexions de notre application, et cela ne me semble pas tout à fait correct non plus.
Quelle est la méthode préférée, standard ou optimale pour configurer une application Java afin qu'elle accepte un certificat auto-signé ? Puis-je atteindre tous les objectifs que j'ai à l'esprit ci-dessus, ou vais-je devoir faire des compromis ? Existe-t-il une option impliquant des fichiers, des répertoires et des paramètres de configuration, et peu ou pas de code ?
0 votes
Petite réparation qui fonctionne : rgagnon.com/javadetails/
23 votes
@Hasenpriester : s'il vous plaît, ne suggérez pas cette page. Elle désactive toute vérification de confiance. Vous n'allez pas seulement accepter le certificat auto-signé que vous voulez, vous allez aussi accepter n'importe quel certificat qu'un attaquant MITM vous présentera.