SOAP消息到webservice – HTTP响应代码:403用于URL

我尝试将XML文件中的SOAP消息发送到Web服务,然后获取二进制输出并对其进行解码。 端点使用HTTPS协议,因此我在代码中使用了TrustManager来避免PKIX问题。 你可以在这里看到我的代码:

 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(); } } 

我执行此操作时会收到以下错误代码。

线程“main”中的exceptionjava.io.IOException:服务器返回HTTP响应代码:403为URL

您的实现没问题,问题实际上与您的Content-Type标头有关。

text/xml; charset=utf-8 text/xml; charset=utf-8是SOAP 1.1的默认Content-Type ,可能不是您的版本。 SOAP 1.2需要一个类型为application/soap+xml; charset=utf-8的头文件application/soap+xml; charset=utf-8 application/soap+xml; charset=utf-8 ,所以将你的代码行更改为下面的代码就可以了:

 httpConn.setRequestProperty("Content-Type", "application/soap+xml; charset=utf-8"); 

在SoapUI中,可以检查调用请求的标头并转到窗口底部的Headers选项卡:

在此处输入图像描述

然后,您可以比较应用程序配置和SoapUI配置之间的差异。

403错误可能与发送到服务器的soap请求标头有关。 所有主机有效将允许您的Java App信任URL的SSL证书。 检查您的服务器是否期望带有用户名/密码的soap标头。 如果您有权访问此服务器,则可以通过Web服务器登录请求失败的位置。 错误代码指向缺少Soap标头,特别是使用用户名和密码的Soap标头

不知道您的SOAP请求是否包含SAML等标头中的任何类型的身份validation信息。 一个选项是,在上面的代码中,您读取文件并将数据发送到服务器,而不是将其发送到服务器,您将其转储到另一个文件。 转储byteoutputstream。 然后从该文件中复制文本并将其放入SOAP UI并尝试运行该文件。 那样有用吗?

在类似的情况下,我们已经有一段时间了,只要尝试TrustManager没有按预期工作,我们就可以通过将证书从服务器安装到JVM的密钥库(用于运行应用程序的JVM)来克服这个问题。 有关如何执行此操作的更多信息,您可以在多个post中找到,例如如何将.cer证书导入Java密钥库?

我知道这是一种强制JVM接受SSL证书的尝试,并且这种function在应用程序上下文中会更好,但只要我们构建在特定应用程序服务器中运行的Web应用程序,实现的解决方案就是接受了一个。