16

我尝试将文件中的SOAP消息发送XML到 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”java.io.IOException 中的异常:服务器返回 HTTP 响应代码:URL 为 403

4

4 回答 4

7

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

该值text/xml; charset=utf-8是 SOAP 1.1 的默认值Content-Type,它可能不是您的版本。SOAP 1.2 需要一个 type 的标头application/soap+xml; charset=utf-8,因此将您的代码行更改为下面的代码会使其正常工作:

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

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

在此处输入图像描述

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

于 2017-08-20T12:28:38.230 回答
2

403 错误可能与您发送到服务器的soap 请求标头有关。所有有效的主机都将允许您的 Java 应用程序信任 URL 的 SSL 证书。检查您的服务器是否需要带有用户名/密码的soap标头。如果您有权访问此服务器,则可以通过 Web 服务器日志检查您的请求失败的位置。错误代码指向缺少 Soap 标头,尤其是带有用户名和密码的 Soap 标头

于 2017-08-21T13:43:53.100 回答
1

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

于 2017-08-22T05:59:36.613 回答
0

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

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

于 2017-08-22T06:02:18.597 回答