J'essaie d'envoyer un message SOAP
dans un fichier XML
à un service Web, puis de récupérer la sortie binaire et de la décoder. Endpoint utilise le protocole HTTPS
. J'ai donc utilisé TrustManager
dans mon code pour éviter les problèmes PKIX
. Vous pouvez voir mon code ici:
import javax.net.ssl.*;
import Java.io.*;
import Java.net.HttpURLConnection;
import Java.net.URL;
import Java.net.URLConnection;
import Java.security.cert.X509Certificate;
public class Main{
public static void sendSoapRequest() throws Exception {
String SOAPUrl = "URL HERE";
String xmlFile2Send = ".\\src\\request.xml";
String responseFileName = ".\\src\\response.xml";
String inputLine;
TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
public Java.security.cert.X509Certificate[] getAcceptedIssuers() { return null; }
public void checkClientTrusted(X509Certificate[] certs, String authType) { }
public void checkServerTrusted(X509Certificate[] certs, String authType) { }
} };
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new Java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Create all-trusting Host name verifier
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) { return true; }
};
// Install the all-trusting Host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
// Create the connection with http
URL url = new URL(SOAPUrl);
URLConnection connection = url.openConnection();
HttpURLConnection httpConn = (HttpURLConnection) connection;
FileInputStream fin = new FileInputStream(xmlFile2Send);
ByteArrayOutputStream bout = new ByteArrayOutputStream();
copy(fin, bout);
fin.close();
byte[] b = bout.toByteArray();
StringBuffer buf=new StringBuffer();
String s=new String(b);
b=s.getBytes();
// Set the appropriate HTTP parameters.
httpConn.setRequestProperty("Content-Length", String.valueOf(b.length));
httpConn.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
httpConn.setRequestProperty("SOAPAction", "");
httpConn.setRequestMethod("POST");
httpConn.setDoOutput(true);
OutputStream out = httpConn.getOutputStream();
out.write(b);
out.close();
// Read the response.
httpConn.connect();
System.out.println("http connection status :"+ httpConn.getResponseMessage());
InputStreamReader isr = new InputStreamReader(httpConn.getInputStream());
BufferedReader in = new BufferedReader(isr);
while ((inputLine = in.readLine()) != null)
System.out.println(inputLine);
FileOutputStream fos=new FileOutputStream(responseFileName);
copy(httpConn.getInputStream(),fos);
in.close();
}
public static void copy(InputStream in, OutputStream out) throws IOException {
synchronized (in) {
synchronized (out) {
byte[] buffer = new byte[256];
while (true) {
int bytesRead = in.read(buffer);
if (bytesRead == -1)
break;
out.write(buffer, 0, bytesRead);
}
}
}
}
public static void main(String args[]) throws Exception {
sendSoapRequest();
}
}
Je reçois le code d'erreur suivant lorsque je l'exécute.
Exception dans le thread "principal" Java.io.IOException: le serveur a renvoyé HTTP code de réponse: 403 pour l'URL
Votre implémentation est correcte, le problème est lié à votre en-tête Content-Type
, en fait.
La valeur text/xml; charset=utf-8
est la valeur par défaut Content-Type
de SOAP 1.1, qui n'est probablement pas la version de la vôtre. SOAP 1.2 attend un en-tête de type application/soap+xml; charset=utf-8
, si vous modifiez votre ligne de code par celle-ci, cela fonctionnera:
httpConn.setRequestProperty("Content-Type", "application/soap+xml; charset=utf-8");
Dans SoapUI, il est possible de vérifier les en-têtes appelant la demande et allant à l'onglet Headers en bas de la fenêtre:
Ensuite, vous pouvez comparer les différences entre les configurations de votre application et celles de SoapUI.
Une erreur 403 peut être liée à l'envoi des en-têtes de votre requête soap au serveur . Tous les hôtes valides permettront à votre application Java de faire confiance au certificat SSL pour l'URL . Vérifiez si votre serveur attend un en-tête soap avec nom d'utilisateur/mot de passe. Si vous avez accès à ce serveur, vous pouvez vérifier, via les journaux du serveur Web, où votre demande échoue. Le code d'erreur pointe vers l'en-tête de savon manquant, en particulier les en-têtes de savon avec nom d'utilisateur et mot de passe
Vous vous demandez si votre demande SOAP contient des informations d'authentification dans des en-têtes tels que SAML. Une option est, dans le code ci-dessus, où vous lisez le fichier et envoyez les données au serveur, au lieu de les envoyer au serveur, vous les sauvegardez dans un autre fichier. Vide ce byteoutputstream. Copiez ensuite le texte de ce fichier et mettez-le dans l'interface utilisateur SOAP, puis essayez de l'exécuter. Ça marche?
Dans une situation similaire, cela faisait longtemps que, et tant que TrustManager
n’avait pas fonctionné comme prévu, nous avons réussi à surmonter ce problème en installant le certificat du serveur sur le magasin de clés de la JVM (JVM utilisé pour exécuter l’application). Vous trouverez plus d’informations sur la procédure à suivre dans plusieurs articles, tels que Comment importer un certificat .cer dans un magasin de clés Java?
Je suis conscient du fait que nous essayons de forcer JVM à accepter les certificats SSL et que cette fonctionnalité serait préférable pour vivre dans le contexte de l'application, mais tant que nous construisions une application Web exécutée sur des serveurs d'applications spécifiques, la solution implémentée était une solution intégrée. accepté un.