Apache Axis 1.4:通过HTTP代理调用HTTPS服务器SOAP API遇异常
首先得把你碰到的Unrecognized SSL message, plaintext connection?错误说透:这通常是客户端给明文HTTP端口发了SSL握手请求,或者服务器返回明文但客户端在等SSL响应。结合你的场景,大概率是Axis客户端的配置出了问题,要么地址写错了,要么传输协议没弄对。
下面一步步排查解决:
1. 先确认Axis调用的目标地址是否正确
你搭的Apache代理是把http://proxyIP/foo转发到后端的https://mainIP/,那Axis客户端必须直接调用这个HTTP代理地址,而不是原HTTPS地址。如果代码里还写着https://mainIP/,哪怕设了代理,JDK6的SSL栈因为不支持SNI也连不上后端;更糟的是如果误把代理地址写成HTTPS开头(比如https://proxyIP/foo),客户端会给代理的80端口发SSL握手请求,代理返回明文HTTP响应,直接触发这个错误。
检查你的Axis代码,确保服务地址是HTTP的代理地址:
Service service = new Service(); Call call = (Call) service.createCall(); // 这里必须是http://proxyIP/foo,不是原HTTPS地址也不是https开头的代理地址 call.setTargetEndpointAddress(new URL("http://proxyIP/foo"));
2. 调整Axis的传输配置,禁用强制SSL
如果你的Axis客户端之前配置过强制使用HTTPS传输(比如修改过client-config.wsdd),得确保调用HTTP代理地址时用的是明文HTTP传输。
打开client-config.wsdd,确认有HTTP传输器的配置:
<transport name="http" pivot="java:org.apache.axis.transport.http.HTTPSender"/>
并且在代码里明确指定使用HTTP传输协议:
call.setTransportProtocol("http");
3. 验证Apache代理的配置是否正常
虽然你说手动测试正常,但还是再确认下代理是否正确处理SOAP请求。用curl模拟Axis的请求:
curl http://proxyIP/foo -H "Content-Type: text/xml" -d @your-soap-request.xml
如果能拿到正确的SOAP响应,说明代理没问题,问题肯定在Axis客户端这边。
另外,确保Apache代理的SSL配置支持TLS1.2和SNI(毕竟后端需要),配置大概是这样:
ProxyPass /foo https://mainIP/ ProxyPassReverse /foo https://mainIP/ # 启用TLS1.2,禁用旧协议 SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1 SSLHonorCipherOrder on
Apache默认会在和后端握手时发送SNI,所以这部分不用额外配置。
4. 排查Axis1.4的HttpClient兼容性问题
Axis1.4默认用的是HttpClient 3.x,如果你的代理需要特殊的HTTP处理(比如编码、认证),可以调整HttpClient的配置。不过你的场景是反向代理,直接访问代理地址即可,一般不需要额外设置代理参数。
如果之前给Axis配置过正向代理(比如通过System.setProperty设置http.proxyHost),记得把这些配置去掉,因为现在是直接访问反向代理的地址,不需要走正向代理。
最后总结最可能的原因
90%的概率是你Axis代码里的目标地址写错了——要么用了原HTTPS地址,要么把代理地址写成了HTTPS开头。只要改成http://proxyIP/foo,再确保传输协议是HTTP,这个SSL异常应该就能解决。
内容的提问来源于stack exchange,提问作者Dracam

