使用Dropbox Java SDK for API v2时获取SSLHandshakeException

XPages应用程序中,我想利用用于API v2Dropbox Java SDK(2.1.2)来获取有关我的Dropbox帐户的信息。 以下代码用于检索相应的帐户对象:

String atoken = "****"; DbxRequestConfig rc = new DbxRequestConfig("****"); DbxClientV2 client = new DbxClientV2(rc,atoken); DbxUserUsersRequests users = client.users(); FullAccount acc = users.getCurrentAccount(); // Exception raised here 

最后一行引发以下exception:

 com.dropbox.core.NetworkIOException: No appropriate protocol at com.dropbox.core.DbxRequestUtil.startPostRaw(DbxRequestUtil.java:240) ... Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol at com.ibm.jsse2.kb.c(kb.java:347) ... 

堆栈跟踪中我得出结论, IBMJSSE2是用于处理SSL握手的安全提供程序。 所以我在非Domino JVM(JRE7)中运行了上面的代码,它使用了SunJSSE安全提供程序,并且没有任何问题。 因此问题必须与IBM的Domino JVM有关,但我无法弄清楚如何修复它。

任何人都可以帮我解决这个问题或提供解决方案吗?


其他信息

Domino服务器的版本: 9.0.1 FP4 HF70

Java运行时版本:pwa6460sr16fp4-20150414_01(SR16 FP4)[22B8:0002-1E88]

JVM版本: JRE 1.6.0 IBM J9 2.4 Windows 7 amd64-64 jvmwa6460sr16fp4-20150406_242976(已启用JIT,已启用AOT)J9VM – 20150406_242976 JIT – r9_20150402_88984 GC – GA24_Java6_SR16_20150406_1410_B242976

Domino JVM中已安装不受限制的JCE策略文件。

IBMJSSE2安全提供程序的属性:

 Alg.Alias.TrustManagerFactory.IbmPKIX = PKIX Alg.Alias.TrustManagerFactory.X.509 = PKIX Alg.Alias.TrustManagerFactory.X509 = PKIX KeyManagerFactory.IbmX509 = com.ibm.jsse2.rc$a_ KeyManagerFactory.NewIbmX509 = com.ibm.jsse2.rc$b_ Provider.id className = com.ibm.jsse2.IBMJSSEProvider2 Provider.id info = IBM JSSE provider2 (implements IbmX509 key/trust factories, SSLv3, TLSv1) Provider.id name = IBMJSSE2 Provider.id version = 1.6 SSLContext.Default = com.ibm.jsse2.tc SSLContext.SSL = com.ibm.jsse2.uc SSLContext.SSL_TLS = com.ibm.jsse2.vc SSLContext.SSL_TLSv2 = com.ibm.jsse2.wc SSLContext.TLS = com.ibm.jsse2.yc SSLContext.TLSv1 = com.ibm.jsse2.zc SSLContext.TLSv1.1 = com.ibm.jsse2.ad SSLContext.TLSv1.2 = com.ibm.jsse2.bd TrustManagerFactory.IbmX509 = com.ibm.jsse2.ed$b_ TrustManagerFactory.PKIX = com.ibm.jsse2.ed$a_ 

exception的完全堆栈跟踪:

 com.dropbox.core.NetworkIOException: No appropriate protocol at com.dropbox.core.DbxRequestUtil.startPostRaw(DbxRequestUtil.java:240) at com.dropbox.core.v2.DbxRawClientV2$1.execute(DbxRawClientV2.java:100) at com.dropbox.core.v2.DbxRawClientV2.executeRetriable(DbxRawClientV2.java:256) at com.dropbox.core.v2.DbxRawClientV2.rpcStyle(DbxRawClientV2.java:97) at com.dropbox.core.v2.users.DbxUserUsersRequests.getCurrentAccount(DbxUserUsersRequests.java:120) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:60) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37) at java.lang.reflect.Method.invoke(Method.java:611) at com.ibm.jscript.types.JavaAccessObject.call(JavaAccessObject.java:321) at com.ibm.jscript.types.FBSObject.call(FBSObject.java:161) at com.ibm.jscript.ASTTree.ASTCall.interpret(ASTCall.java:197) at com.ibm.jscript.ASTTree.ASTAssign.interpret(ASTAssign.java:91) at com.ibm.jscript.ASTTree.ASTBlock.interpret(ASTBlock.java:100) at com.ibm.jscript.ASTTree.ASTTry.interpret(ASTTry.java:109) at com.ibm.jscript.ASTTree.ASTBlock.interpret(ASTBlock.java:100) at com.ibm.jscript.ASTTree.ASTTry.interpret(ASTTry.java:109) at com.ibm.jscript.std.FunctionObject._executeFunction(FunctionObject.java:261) at com.ibm.jscript.std.FunctionObject.executeFunction(FunctionObject.java:185) at com.ibm.jscript.std.FunctionObject.call(FunctionObject.java:171) at com.ibm.jscript.types.FBSObject.call(FBSObject.java:161) at com.ibm.jscript.ASTTree.ASTCall.interpret(ASTCall.java:197) at com.ibm.jscript.ASTTree.ASTAssign.interpret(ASTAssign.java:91) at com.ibm.jscript.ASTTree.ASTBlock.interpret(ASTBlock.java:100) at com.ibm.jscript.ASTTree.ASTIf.interpret(ASTIf.java:85) at com.ibm.jscript.ASTTree.ASTProgram.interpret(ASTProgram.java:119) at com.ibm.jscript.types.FBSGlobalObject$GlobalMethod.call(FBSGlobalObject.java:280) at com.ibm.jscript.types.FBSObject.call(FBSObject.java:161) at com.ibm.jscript.types.FBSGlobalObject$GlobalMethod.call(FBSGlobalObject.java:219) at com.ibm.jscript.ASTTree.ASTCall.interpret(ASTCall.java:197) at com.ibm.jscript.ASTTree.ASTBlock.interpret(ASTBlock.java:100) at com.ibm.jscript.ASTTree.ASTIf.interpret(ASTIf.java:85) at com.ibm.jscript.ASTTree.ASTBlock.interpret(ASTBlock.java:100) at com.ibm.jscript.ASTTree.ASTTry.interpret(ASTTry.java:109) at com.ibm.jscript.std.FunctionObject._executeFunction(FunctionObject.java:261) at com.ibm.jscript.std.FunctionObject.executeFunction(FunctionObject.java:185) at com.ibm.jscript.std.FunctionObject.call(FunctionObject.java:171) at com.ibm.jscript.std.FunctionPrototype$FunctionMethod.call(FunctionPrototype.java:169) at com.ibm.jscript.types.FBSObject.call(FBSObject.java:161) at com.ibm.jscript.ASTTree.ASTCall.interpret(ASTCall.java:197) at com.ibm.jscript.ASTTree.ASTAssign.interpret(ASTAssign.java:91) at com.ibm.jscript.ASTTree.ASTBlock.interpret(ASTBlock.java:100) at com.ibm.jscript.ASTTree.ASTIf.interpret(ASTIf.java:85) at com.ibm.jscript.ASTTree.ASTBlock.interpret(ASTBlock.java:100) at com.ibm.jscript.ASTTree.ASTTry.interpret(ASTTry.java:109) at com.ibm.jscript.ASTTree.ASTProgram.interpret(ASTProgram.java:119) at com.ibm.jscript.ASTTree.ASTProgram.interpretEx(ASTProgram.java:139) at com.ibm.jscript.JSExpression._interpretExpression(JSExpression.java:435) at com.ibm.jscript.JSExpression.access$1(JSExpression.java:424) at com.ibm.jscript.JSExpression$2.run(JSExpression.java:414) at java.security.AccessController.doPrivileged(AccessController.java:448) at com.ibm.jscript.JSExpression.interpretExpression(JSExpression.java:410) at com.ibm.jscript.JSExpression.evaluateValue(JSExpression.java:251) at com.ibm.jscript.JSExpression.evaluateValue(JSExpression.java:234) at com.ibm.xsp.javascript.JavaScriptInterpreter.interpret(JavaScriptInterpreter.java:222) at com.ibm.xsp.binding.javascript.JavaScriptMethodBinding.invoke(JavaScriptMethodBinding.java:111) at com.ibm.xsp.component.UIViewRootEx.invokePhaseMethodBinding(UIViewRootEx.java:1735) at com.ibm.xsp.controller.FacesControllerImpl.invokePhaseMethodBinding(FacesControllerImpl.java:450) at com.ibm.xsp.controller.FacesControllerImpl.access$0(FacesControllerImpl.java:444) at com.ibm.xsp.controller.FacesControllerImpl$ViewPhaseListener.afterPhase(FacesControllerImpl.java:512) at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:218) at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:120) at com.ibm.xsp.controller.FacesControllerImpl.render(FacesControllerImpl.java:270) at com.ibm.xsp.webapp.FacesServlet.serviceView(FacesServlet.java:261) at com.ibm.xsp.webapp.FacesServletEx.serviceView(FacesServletEx.java:157) at com.ibm.xsp.webapp.FacesServlet.service(FacesServlet.java:160) at com.ibm.xsp.webapp.FacesServletEx.service(FacesServletEx.java:138) at com.ibm.xsp.webapp.DesignerFacesServlet.service(DesignerFacesServlet.java:103) at com.ibm.designer.runtime.domino.adapter.ComponentModule.invokeServlet(ComponentModule.java:576) at com.ibm.domino.xsp.module.nsf.NSFComponentModule.invokeServlet(NSFComponentModule.java:1335) at com.ibm.designer.runtime.domino.adapter.ComponentModule$AdapterInvoker.invokeServlet(ComponentModule.java:853) at com.ibm.designer.runtime.domino.adapter.ComponentModule$ServletInvoker.doService(ComponentModule.java:796) at com.ibm.designer.runtime.domino.adapter.ComponentModule.doService(ComponentModule.java:565) at com.ibm.domino.xsp.module.nsf.NSFComponentModule.doService(NSFComponentModule.java:1319) at com.ibm.domino.xsp.module.nsf.NSFService.doServiceInternal(NSFService.java:662) at com.ibm.domino.xsp.module.nsf.NSFService.doService(NSFService.java:482) at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.doService(LCDEnvironment.java:357) at com.ibm.designer.runtime.domino.adapter.LCDEnvironment.service(LCDEnvironment.java:313) at com.ibm.domino.xsp.bridge.http.engine.XspCmdManager.service(XspCmdManager.java:272) Caused by: javax.net.ssl.SSLHandshakeException: No appropriate protocol at com.ibm.jsse2.kb.c(kb.java:347) at com.ibm.jsse2.SSLSocketImpl.i(SSLSocketImpl.java:363) at com.ibm.jsse2.SSLSocketImpl.h(SSLSocketImpl.java:650) at com.ibm.jsse2.SSLSocketImpl.a(SSLSocketImpl.java:669) at com.ibm.jsse2.SSLSocketImpl.startHandshake(SSLSocketImpl.java:95) at com.ibm.net.ssl.www2.protocol.https.c.afterConnect(c.java:162) at com.ibm.net.ssl.www2.protocol.https.d.connect(d.java:36) at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1044) at com.ibm.net.ssl.www2.protocol.https.b.getOutputStream(b.java:53) at com.dropbox.core.http.StandardHttpRequestor.getOutputStream(StandardHttpRequestor.java:123) at com.dropbox.core.http.StandardHttpRequestor.access$000(StandardHttpRequestor.java:28) at com.dropbox.core.http.StandardHttpRequestor$Uploader.(StandardHttpRequestor.java:133) at com.dropbox.core.http.StandardHttpRequestor.startPost(StandardHttpRequestor.java:72) at com.dropbox.core.http.StandardHttpRequestor.startPost(StandardHttpRequestor.java:28) at com.dropbox.core.DbxRequestUtil.startPostRaw(DbxRequestUtil.java:232) ... 

更新 :设置javax.net.debug=ssl:handshake:data (由Jigar Joshi建议)后,错误日志和跟踪日志提供以下附加信息:

证书主题为EMAILADDRESS = ****,CN = ****,O = ****,L = ****,ST = ****,C = ****,由CN = *颁发***,OU = ****,O = ****,C = ****, 不受信任。 validation失败,错误3659

 CommonBaseEventLogRecord:sourceClassName = com.ibm.domino.napi.ssl.DominoX509TrustManager CommonBaseEventLogRecord:sourceMethodName = checkServerTrusted  

不受信任的证书是我自己的 ,即使所有证书和私钥都已导入我的密钥库。 密钥库在非Domino JVM中工作的事实允许我断定密钥库文件应该是有效的。 但是,在Domino JVM中运行代码时,证书仍然不受信任。


更新 :调试输出的核心部分( javax.net.debug=ssl:handshake )是

 SSLContextImpl: Using X509ExtendedKeyManager com.ibm.jsse2.hd SSLContextImpl: Using X509TrustManager com.ibm.jsse2.pc IBMJSSE2 will ignore com.ibm.jsse2.overrideDefaultProtocol since was set to a non recognized value TLSv1 Installed Providers = IBMJSSE2, IBMJCE, IBMJGSSProvider, IBMCertPath, IBMSASL, IBMXMLCRYPTO, IBMXMLEnc, Policy, IBMSPNEGO JsseJCE: Using SecureRandom IBMSecureRandom from provider IBMJCE version 1.2 trigger seeding of SecureRandom done seeding SecureRandom IBMJSSE2 will enable CBC protection IBMJSSE2 to send SCSV Cipher Suite on initial ClientHello JsseJCE: Using SecureRandom IBMSecureRandom from provider IBMJCE version 1.2 IBMJSSE2 will allow RFC 5746 renegotiation per com.ibm.jsse2.renegotiate set to none or default IBMJSSE2 will not require renegotiation indicator during initial handshake per com.ibm.jsse2.renegotiation.indicator set to OPTIONAL or default taken IBMJSSE2 will not perform identity checking against the peer cert check during renegotiation per com.ibm.jsse2.renegotiation.peer.cert.check set to OFF or default IBMJSSE2 will not allow unsafe server certificate change during renegotiation per jdk.tls.allowUnsafeServerCertChange set to FALSE or default Is initial handshake: true JsseJCE: Using KeyAgreement ECDH from provider IBMJCE version 1.2 JsseJCE: Using signature SHA1withECDSA from provider TBD via init JsseJCE: Using signature NONEwithECDSA from provider TBD via init JsseJCE: Using KeyFactory EC from provider IBMJCE version 1.2 JsseJCE: Using KeyPairGenerator EC from provider TBD via init JsseJce: EC is available Ignoring disabled cipher suite: SSL_RENEGO_PROTECTION_REQUEST for TLSv1 No available cipher suite for TLSv1 Thread-8, handling exception: javax.net.ssl.SSLHandshakeException: No appropriate protocol Thread-8, SEND TLSv1 ALERT: fatal, description = handshake_failure 

没有可用的TLSv1密码套件 ”似乎是我问题的根源。


更新 :获取默认的SSL服务器套接字工厂( SSLServerSocketFactory.getDefault() )以及相应的默认和支持的密码套件( getDefaultCipherSuites() / getSupportedCipherSuites() )显示只有SSL密码套件可用:

 SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA [supported] SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA [default] SSL_DHE_DSS_WITH_AES_128_CBC_SHA [default] SSL_DHE_DSS_WITH_AES_128_CBC_SHA256 [supported] SSL_DHE_DSS_WITH_AES_128_GCM_SHA256 [supported] SSL_DHE_DSS_WITH_AES_256_CBC_SHA [default] SSL_DHE_DSS_WITH_AES_256_CBC_SHA256 [supported] SSL_DHE_DSS_WITH_AES_256_GCM_SHA384 [supported] SSL_DHE_DSS_WITH_DES_CBC_SHA [default] SSL_DHE_DSS_WITH_RC4_128_SHA [supported] SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA [supported] SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA [default] SSL_DHE_RSA_WITH_AES_128_CBC_SHA [default] SSL_DHE_RSA_WITH_AES_128_CBC_SHA256 [supported] SSL_DHE_RSA_WITH_AES_128_GCM_SHA256 [supported] SSL_DHE_RSA_WITH_AES_256_CBC_SHA [default] SSL_DHE_RSA_WITH_AES_256_CBC_SHA256 [supported] SSL_DHE_RSA_WITH_AES_256_GCM_SHA384 [supported] SSL_DHE_RSA_WITH_DES_CBC_SHA [default] SSL_DH_anon_EXPORT_WITH_DES40_CBC_SHA [supported] SSL_DH_anon_EXPORT_WITH_RC4_40_MD5 [supported] SSL_DH_anon_WITH_3DES_EDE_CBC_SHA [supported] SSL_DH_anon_WITH_AES_128_CBC_SHA [supported] SSL_DH_anon_WITH_AES_128_CBC_SHA256 [supported] SSL_DH_anon_WITH_AES_128_GCM_SHA256 [supported] SSL_DH_anon_WITH_AES_256_CBC_SHA [supported] SSL_DH_anon_WITH_AES_256_CBC_SHA256 [supported] SSL_DH_anon_WITH_AES_256_GCM_SHA384 [supported] SSL_DH_anon_WITH_DES_CBC_SHA [supported] SSL_DH_anon_WITH_RC4_128_MD5 [supported] SSL_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA [supported] SSL_ECDHE_ECDSA_WITH_AES_128_CBC_SHA [supported] SSL_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 [supported] SSL_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 [supported] SSL_ECDHE_ECDSA_WITH_AES_256_CBC_SHA [supported] SSL_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 [supported] SSL_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 [supported] SSL_ECDHE_ECDSA_WITH_NULL_SHA [supported] SSL_ECDHE_ECDSA_WITH_RC4_128_SHA [supported] SSL_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA [supported] SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA [supported] SSL_ECDHE_RSA_WITH_AES_128_CBC_SHA256 [supported] SSL_ECDHE_RSA_WITH_AES_128_GCM_SHA256 [supported] SSL_ECDHE_RSA_WITH_AES_256_CBC_SHA [supported] SSL_ECDHE_RSA_WITH_AES_256_CBC_SHA384 [supported] SSL_ECDHE_RSA_WITH_AES_256_GCM_SHA384 [supported] SSL_ECDHE_RSA_WITH_NULL_SHA [supported] SSL_ECDHE_RSA_WITH_RC4_128_SHA [supported] SSL_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA [supported] SSL_ECDH_ECDSA_WITH_AES_128_CBC_SHA [supported] SSL_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 [supported] SSL_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 [supported] SSL_ECDH_ECDSA_WITH_AES_256_CBC_SHA [supported] SSL_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 [supported] SSL_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 [supported] SSL_ECDH_ECDSA_WITH_NULL_SHA [supported] SSL_ECDH_ECDSA_WITH_RC4_128_SHA [supported] SSL_ECDH_RSA_WITH_3DES_EDE_CBC_SHA [supported] SSL_ECDH_RSA_WITH_AES_128_CBC_SHA [supported] SSL_ECDH_RSA_WITH_AES_128_CBC_SHA256 [supported] SSL_ECDH_RSA_WITH_AES_128_GCM_SHA256 [supported] SSL_ECDH_RSA_WITH_AES_256_CBC_SHA [supported] SSL_ECDH_RSA_WITH_AES_256_CBC_SHA384 [supported] SSL_ECDH_RSA_WITH_AES_256_GCM_SHA384 [supported] SSL_ECDH_RSA_WITH_NULL_SHA [supported] SSL_ECDH_RSA_WITH_RC4_128_SHA [supported] SSL_ECDH_anon_WITH_3DES_EDE_CBC_SHA [supported] SSL_ECDH_anon_WITH_AES_128_CBC_SHA [supported] SSL_ECDH_anon_WITH_AES_256_CBC_SHA [supported] SSL_ECDH_anon_WITH_NULL_SHA [supported] SSL_ECDH_anon_WITH_RC4_128_SHA [supported] SSL_KRB5_EXPORT_WITH_DES_CBC_40_MD5 [supported] SSL_KRB5_EXPORT_WITH_DES_CBC_40_SHA [supported] SSL_KRB5_EXPORT_WITH_RC4_40_MD5 [supported] SSL_KRB5_EXPORT_WITH_RC4_40_SHA [supported] SSL_KRB5_WITH_3DES_EDE_CBC_MD5 [supported] SSL_KRB5_WITH_3DES_EDE_CBC_SHA [supported] SSL_KRB5_WITH_DES_CBC_MD5 [supported] SSL_KRB5_WITH_DES_CBC_SHA [supported] SSL_KRB5_WITH_RC4_128_MD5 [supported] SSL_KRB5_WITH_RC4_128_SHA [supported] SSL_RSA_EXPORT_WITH_DES40_CBC_SHA [supported] SSL_RSA_EXPORT_WITH_RC4_40_MD5 [supported] SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA [default] SSL_RSA_FIPS_WITH_DES_CBC_SHA [default] SSL_RSA_WITH_3DES_EDE_CBC_SHA [default] SSL_RSA_WITH_AES_128_CBC_SHA [default] SSL_RSA_WITH_AES_128_CBC_SHA256 [supported] SSL_RSA_WITH_AES_128_GCM_SHA256 [supported] SSL_RSA_WITH_AES_256_CBC_SHA [default] SSL_RSA_WITH_AES_256_CBC_SHA256 [supported] SSL_RSA_WITH_AES_256_GCM_SHA384 [supported] SSL_RSA_WITH_DES_CBC_SHA [default] SSL_RSA_WITH_NULL_MD5 [supported] SSL_RSA_WITH_NULL_SHA [supported] SSL_RSA_WITH_NULL_SHA256 [supported] SSL_RSA_WITH_RC4_128_MD5 [supported] SSL_RSA_WITH_RC4_128_SHA [supported] 

谁能告诉我如何在服务器sockets工厂中提供TLS密码套件?

回覆

 com.dropbox.core.NetworkIOException: No appropriate protocol 

我最好的猜测是,这一行强烈暗示了你的问题:

 Provider.id info = IBM JSSE provider2 (implements IbmX509 key/trust factories, SSLv3, TLSv1) 

“没有合适的协议”听起来好像它可能告诉你端点不支持SSLv3或TLSv1。

我不知道Dropbox,但由于已知的安全问题,许多服务提供商都在弃用这些旧协议。

您可以在这两个 IBM技术说明中找到一些有用的信息。

问题似乎是Dropbox Java SDK基于硬编码列表限制 SSL套接字中启用的密码套件 。 该列表中的所有相关密码套件名称均以TLS_ ”开头。 但是,在Domino JVM密码套件中,名称始终以“ SSL_ ”开头,即使它们所涉及的SSL上下文具有协议TLSv1或更高版本。

我现在已经停止使用Dropbox Java SDK,并通过使用HttpsUrlConnection发布HTTPpost开始使用Dropbox API。 这不如Java SDK那么方便,但至少与TLSv1的SSL握手按预期工作。