通过.NET或Java访问RPC /编码SOAP Web服务

时间:2018-08-27 15:17:12

标签: .net soap encoding wsdl rpc

我正在尝试基于rpc /编码格式与SOAP Web服务进行通信。它是外部Web服务,因此无法更改。它通过SSL进行保护,并且身份验证基于X509证书。

我已经使用openssl命令创建了未签名的证书和密钥文件:

openssl req -new -sha256 -newkey rsa:2048 -nodes -keyout keyfile.key -out unsigned.pem -subj '/O= <Company_name>/OU=WebApi/CN=<uid>'

,然后收到已签名的pem文件(将其命名为signed.pem)。我已将BEGIN CERTIFICATE / END CERTIFICATE内容与BEGIN PRIVATE KEY / END PRIVATE KEY内容合并到一个文件中。然后,我使用此文件(将其命名为final.pem)进行身份验证。

我有用PHP编写的简单示例代码,它确实有效:

$client = new SoapClient('https://www.url.to.external.web.service?wsdl', 
array('local_cert' => "final.pem"));
$result = $client->Login();

现在我正在努力将此代码移植到.NET或Java,但更喜欢使用.NET。我会记下我的所作所为和取得的结果。

.NET

已安装xmlrpcnet库,因为我已经了解到.NET不支持现成的RPC /编码格式。我创建了代理界面:

[XmlRpcUrl("https://www.url.to.external.web.service?wsdl")]
[ServiceContract]
public interface WebServiceProxy : IXmlRpcProxy
{
    [XmlRpcMethod("Login")]
    [OperationContract(Action = "Login")]
    LoginReturn Login();
}

稍后,我将从final.pem中提取X509Certificate2实例。我是这样做的:

    public X509Certificate2 GetCertificate(string fileName)
    {
        var pem = File.ReadAllText(fileName);
        byte[] certBuffer = GetBytesFromPEM(pem, "CERTIFICATE");
        return new X509Certificate2(certBuffer);
    }

    private byte[] GetBytesFromPEM(string pemString, string section)
    {
        var header = String.Format("-----BEGIN {0}-----", section);
        var footer = String.Format("-----END {0}-----", section);

        var start = pemString.IndexOf(header, StringComparison.Ordinal);
        if (start < 0)
            return null;

        start += header.Length;
        var end = pemString.IndexOf(footer, start, StringComparison.Ordinal) - start;

        if (end < 0)
            return null;

        return Convert.FromBase64String(pemString.Substring(start, end));
    }

最后,我正在创建代理对象,附加证书并调用Login()方法:

var proxy = XmlRpcProxyGen.Create<WebServiceProxy>();
proxy.ClientCertificates.Add(_certificate);
proxy.Login();

但是我收到带有消息“无法创建ssl / tls安全通道”的WebException。

Java:

不幸的是,最新版本的轴库不支持RPC /编码格式,因此我下载了旧的(1.4)。然后使用工具WSDL2Java从WSDL文件生成代理类。后来我使用keytool将final.pem添加到密钥库中:

keytool -import -noprompt -trustcacerts -alias somealias -file final.pem -keystore final.jks -storepass password

并将其加载到Java代码中。然后创建了SSL上下文,创建了代理并调用了login()方法,但是不幸的是我收到了异常。

var certPath = "C:\path\to\final.jks"
var file = new File(certPath);

var keyStore = KeyStore.getInstance(file, "password".toCharArray());

SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
        KeyManagerFactory keyManagerFactory = 
KeyManagerFactory.getInstance("SunX509");

        keyManagerFactory.init(keyStore, "abcABC123".toCharArray());
        sslContext.init(keyManagerFactory.getKeyManagers(), null, null);

Service service = new APILocator("https://www.url.to.external.web.service?wsdl", new QName("http://namespace.com/", "path"));
        URL url = new URL("https://www.url.to.external.web.service?wsdl");
        var proxy = new APIBindingStub(url, service);

        proxy.login();

和我之前提到的错误:

javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure

有人早些时候试图从.NET / Java访问此类Web服务吗?

0 个答案:

没有答案