Un module que j'ajoute à notre grande application Java doit converser avec le site Web sécurisé SSL d'une autre entreprise. Le problème est que le site utilise un certificat auto-signé. J'ai 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 réussisse.
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 aucune gestion supplémentaire en place pour le certificat auto-signé, cela 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 certificat auto-signé, pour celui-ci dans l'application, et nulle part ailleurs.
Je sais que je peux importer le certificat dans le magasin d'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 aider; cela semble très invasif à faire sur toutes les machines de nos clients pour un module qu'ils ne peuvent pas utiliser; cela affecterait toutes les autres applications Java utilisant le même JRE, et je n'aime pas cela même si les chances pour toute autre application Java d'accéder à 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 peux créer une instance de TrustManager qui effectue une vérification personnalisée. Il semble que je pourrais même être en mesure de créer un TrustManager qui délègue au vrai TrustManager dans toutes les instances sauf celui-ci. Mais il semble que TrustManager soit installé globalement, et je suppose que cela affecterait toutes les autres connexions de notre application, et cela ne me semble pas tout à fait normal non plus.
Quelle est la méthode préférée, standard ou la meilleure pour configurer une application Java pour accepter un certificat auto-signé? Puis-je atteindre tous les objectifs que j'ai en tête ci-dessus ou vais-je devoir faire des compromis? Existe-t-il une option impliquant des fichiers et des répertoires et des paramètres de configuration, et peu ou pas de code?