调用WebService并出现SSL /证书问题

TS-*_*TS- 6 java tomcat soap

我将首先介绍一下我在Java中设置密钥库等方面的知识并不多

我正在尝试调用SOAP Web服务,我得到了wsdl,生成了代码等等.在我部署它并尝试触发WS调用之前,一切似乎都没问题.

这是我的设置:

  • Tomcat 7.0.35
  • Java,jdk 1.6.0_39
  • pfx文件和密码
  • 项目作为标准Web应用程序(战争)部署到tomcat

当我运行代码时,我得到以下异常:

Caused by: javax.net.ssl.SSLHandshakeException: SSLHandshakeException invoking https://tallyservices-qa.olson.com/tallyDemo2WebServices/tallyDemo2/sms: Received fatal alert: certificate_unknown
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.mapException(HTTPConduit.java:1336)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1320)
    at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
    at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:622)
    at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
    ... 27 more
Caused by: javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
    at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1837)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1019)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1203)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1230)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1214)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:434)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:166)
    at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1031)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
    at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.setupWrappedStream(URLConnectionHTTPConduit.java:170)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1280)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1231)
    at org.apache.cxf.transport.http.URLConnectionHTTPConduit$URLConnectionWrappedOutputStream.onFirstWrite(URLConnectionHTTPConduit.java:183)
    at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:47)
    at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:69)
    at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1293)
    ... 30 more
Run Code Online (Sandbox Code Playgroud)

我按照这里的建议:如何使用私钥将.pfx文件转换为密钥库?将证书安装到我的密钥库:

keytool -importkeystore -srckeystore C:\somefolder\mypfxfile.pxf -srcstoretype pkcs12 
-destkeystore C:\somefolder\clientcert.jks -deststoretype JKS
Run Code Online (Sandbox Code Playgroud)

我得到了:

Enter destination keystore password: <mypassword>
Re-enter new password: <mypassword>
Enter source keystore password: <pxf_password>
Entry for alias 67eb31f6 successfully imported.
Import command completed:  1 entries successfully imported, 0 entries failed or
cancelled
Run Code Online (Sandbox Code Playgroud)

所以到目前为止一切看起来都很好,我反弹了我的tomcat并再次击中Servlet,我仍然得到同样的错误.

我还缺少什么?我需要告诉tomcat关于证书还是什么?

在此先感谢我在密钥库和证书区域的帮助和道歉.

编辑: 所以我从Carlo Pellegrini的帮助中得知,我需要将密钥库添加到tomcat:所以现在,我的tomcat以另外的JAVA_OPTS参数启动:

"-Djavax.net.ssl.trustStore=C:\somefolder\clientcert.jks -Djavax.net.ssl.trustStorePassword=somepassword"
Run Code Online (Sandbox Code Playgroud)

现在我得到了:

Caused by: javax.net.ssl.SSLException: java.lang.RuntimeException: Unexpected error: java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be non-empty
Run Code Online (Sandbox Code Playgroud)

从这里:错误 - trustAnchors参数必须是非空的并且得到java.security.InvalidAlgorithmParameterException:当使用cas时,trustAnchors参数必须是非空的 - 似乎找不到我的信任库?

我想到了我之前的命令:

keytool -importkeystore -srckeystore C:\somefolder\mypfxfile.pxf -srcstoretype pkcs12 -destkeystore C:\somefolder\clientcert.jks -deststoretype JKS
Run Code Online (Sandbox Code Playgroud)

实际上将pxf放入密钥库,而不是信任

当我检查密钥库列表时:

C:\somefolder>keytool -list -keystore "C:\somefolder\clientcert.jks"
Enter keystore password:

Keystore type: JKS
Keystore provider: SUN

Your keystore contains 1 entry

67eb31f6, 13-Feb-2013, PrivateKeyEntry,
Certificate fingerprint (MD5): ... some fingerprint ...
Run Code Online (Sandbox Code Playgroud)

所以我不确定我在这里错过了什么

Car*_*ini 5

您需要信任服务器证书.这是怎么做的:

使用Chrome(其他borwsers的说明可能会有所不同):

  • 冲浪到服务站点.(例子.https://localhost/myService)
  • 如果浏览器不信任它,请单击Proceed anyway,单击地址栏中的挂锁图标,然后没有弹出窗口,选择Connection选项卡和Certificate Information 链接.
  • 这应该打开证书查看器窗口,选择Details,您应该查看Export ...按钮.选择Base 64编码的单一证书并将其另存为mysite.cer文件.

这将获得证书,现在您需要在信任库中导入它.

现在导入密钥库中的证书:

keytool -import -file mysite.cer -keystore mykeystore
Run Code Online (Sandbox Code Playgroud)

这将mykeystore在当前目录中创建一个新的文件密钥库文件.

最后使用JVM参数启动Web服务客户端应用程序javax.net.ssl.trustStore,如下所示:

java -Djavax.net.ssl.trustStore=mykeystore ... MyClientClass
Run Code Online (Sandbox Code Playgroud)

或者如果您在Windows中使用Tomcat:

set JAVA_OPTS=-Djavax.net.ssl.trustStore=mykeystore
startup.bat
Run Code Online (Sandbox Code Playgroud)

或者如果您在Unix中使用Tomcat:

export JAVA_OPTS="-Djavax.net.ssl.trustStore=mykeystore"
startup.sh
Run Code Online (Sandbox Code Playgroud)


TS-*_*TS- 3

我找到了解决方案,我应该使用 keyStore 而不是 trustStore,但更重要的是,我正在使用的库(cxf 2.7.1)似乎有问题,我必须直接在代码中设置 SSL 属性:

// BEGIN FIX to avoid certificate error, need to set this up in the code for cxf
String storePath = System.getProperty("javax.net.ssl.keyStore");
String storePassword = System.getProperty("javax.net.ssl.keyStorePassword");
String storeType = System.getProperty("javax.net.ssl.keyStoreType");
KeyStore keyStore = KeyStore.getInstance(storeType);
keyStore.load(new FileInputStream(storePath), storePassword.toCharArray());
KeyManagerFactory factory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
factory.init(keyStore, storePassword.toCharArray());
KeyManager[] keyManagers = factory.getKeyManagers();
Client client = ClientProxy.getClient(port);
HTTPConduit conduit = (HTTPConduit) client.getConduit();
conduit.setTlsClientParameters(new TLSClientParameters());
conduit.getTlsClientParameters().setKeyManagers(keyManagers);
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

30789 次

最近记录:

7 年,3 月 前