首先,我将解释一下情景。
我有一个运行jdk1.7.0_79
的WSO2 ESB-4.6.0(使用Apache的HttpClient),我的目标是调用只接受TLSv1.2
协议的外部安全服务,而不更新Java到版本8.
外部服务器指令是:
Supported versions: TLSv1.2
Deflate compression: no
Supported cipher suites (ORDER IS NOT SIGNIFICANT):
TLSv1.2
RSA_WITH_3DES_EDE_CBC_SHA
DHE_RSA_WITH_3DES_EDE_CBC_SHA
RSA_WITH_AES_128_CBC_SHA
DHE_RSA_WITH_AES_128_CBC_SHA
RSA_WITH_AES_256_CBC_SHA
DHE_RSA_WITH_AES_256_CBC_SHA
RSA_WITH_AES_128_CBC_SHA256
RSA_WITH_AES_256_CBC_SHA256
RSA_WITH_CAMELLIA_128_CBC_SHA
DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
DHE_RSA_WITH_AES_128_CBC_SHA256
DHE_RSA_WITH_AES_256_CBC_SHA256
RSA_WITH_CAMELLIA_256_CBC_SHA
DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
TLS_RSA_WITH_AES_128_GCM_SHA256
TLS_RSA_WITH_AES_256_GCM_SHA384
TLS_DHE_RSA_WITH_AES_128_GCM_SHA256
TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
----------------------
Minimal encryption strength: strong encryption (96-bit or more)
Achievable encryption strength: strong encryption (96-bit or more)
BEAST status: protected
CRIME status: protected
因此,构建和调用一个简单的代理,其端点与该服务有关,导致:
Using SSLEngineImpl.
Allow unsafe renegotiation: false
Allow legacy hello messages: true
Is initial handshake: true
Is secure renegotiation: false
HTTPS-Sender I/O dispatcher-1, fatal error: 40: Couldn't kickstart handshaking
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
HTTPS-Sender I/O dispatcher-1, SEND TLSv1 ALERT: fatal, description = handshake_failure
HTTPS-Sender I/O dispatcher-1, WRITE: TLSv1 Alert, length = 2
[2016-02-25 22:15:12,689] ERROR - TargetHandler I/O error: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
javax.net.ssl.SSLHandshakeException: No appropriate protocol (protocol is disabled or cipher suites are inappropriate)
at sun.security.ssl.Handshaker.activate(Handshaker.java:470)
at sun.security.ssl.SSLEngineImpl.kickstartHandshake(SSLEngineImpl.java:714)
at sun.security.ssl.SSLEngineImpl.beginHandshake(SSLEngineImpl.java:740)
at org.apache.http.impl.nio.reactor.SSLIOSession.bind(SSLIOSession.java:141)
at org.apache.http.impl.nio.ssl.SSLClientIOEventDispatch.connected(SSLClientIOEventDispatch.java:205)
at org.apache.http.impl.nio.reactor.BaseIOReactor.sessionCreated(BaseIOReactor.java:250)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.processNewChannels(AbstractIOReactor.java:425)
at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:289)
at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104)
at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:542)
at java.lang.Thread.run(Thread.java:745)
此时,我的第一个想法是找到一种方法来“配置”Java 7以使用它。因此,我确实使用Eclipse(使用javax.xml.soap.SOAPConnectionFactory
)构建了一个简单的Web服务客户端类,并使用与ESB使用的相同的JVM运行它。正如所料,同样的错误!
但是,我编辑了jre/lib/security/java.security
文件并找到了使调用工作的参数:
java MyClientClass -Dhttps.protocols=TLSv1.2 -Dhttps.cipherSuites=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
毕竟,我认为应用于ESB的相同参数应该有效。但是上面的两个参数以及下面的其他参数,在许多不同的组合中,并没有实现,具有与以前相同的例外。
./wso2server.sh -Ddeployment.security.SSLv3=false \
-Ddeployment.security.TLSv1=false \
-Ddeployment.security.TLSv1.1=false \
-Ddeployment.security.TLSv1.2=true \
-Dhttps.protocols=TLSv1.2 \
-Dhttps.cipherSuites=TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
为什么具有相同JVM和相同参数的ESB不起作用,而MyClientClass
呢?问题出在Apache的http-core实现中(作为堆栈跟踪点)?我犯了一些错误,或者这些参数被忽略了?
HttpCore版本是4.1.3。