在使用REST Web服务时,我在解决SSL / TLS错误方面遇到了一些困难。
REST Web服务是使用Spring Framework使用Spring Framework开发的。
客户端是.NET应用程序,使用RestSharp进行REST Web服务消费。
在文件上传过程中,一个客户端出错,一切正常。
System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
此时我还在使用嵌入式Tomcat v8.5.5。在我的Spring Boot应用程序中,我遇到以下错误:
java.lang.NullPointerException: null
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.getSslSupport(NioEndpoint.java:1329) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
// Etc.
java.lang.NullPointerException: null
at org.apache.tomcat.util.net.SecureNioChannel.handshake(SecureNioChannel.java:182) ~[tomcat-embed-core-8.5.5.jar!/:8.5.5]
// Etc.
经过一些研究,我发现this topic有关与嵌入式Tomcat v8.5.5相关的类似错误。根据他们的建议,我将嵌入式Tomcat升级到v8.5.13。
很好,没有更多来自apache Tomcat的NPE。所以,我的.NET应用程序应该工作......或者不工作。
System.Net.WebException: The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
仍然是同样的错误。由于我不再有Tomcat错误,因此我将org.apache
的日志记录级别更改为DEBUG。我在DEBUG级别发现了一些新的错误:
2017-05-10 14:58:05.889 DEBUG 928 --- [-nio-443-exec-4] o.a.tomcat.util.net.SocketWrapperBase : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@3678fe26:org.apache.tomcat.util.net.SecureNioChannel@63c88911:java.nio.channels.SocketChannel[connected local=/... remote=/...]], Read from buffer: [0]
2017-05-10 14:58:05.889 DEBUG 928 --- [-nio-443-exec-4] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
java.io.EOFException: null
at org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper.fillReadBuffer(NioEndpoint.java:1242) ~[tomcat-embed-core-8.5.13.jar!/:8.5.13]
// Etc.
2017-05-10 14:58:05.889 DEBUG 928 --- [-nio-443-exec-4] o.apache.coyote.http11.Http11Processor : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@3678fe26:org.apache.tomcat.util.net.SecureNioChannel@63c88911:java.nio.channels.SocketChannel[connected local=/... remote=/...]], Status in: [OPEN_READ], State out: [CLOSED]
2017-05-10 14:58:05.889 DEBUG 928 --- [-nio-443-exec-4] org.apache.tomcat.util.net.NioEndpoint : Failed to close socket
java.nio.channels.ClosedChannelException: null
at sun.nio.ch.SocketChannelImpl.ensureWriteOpen(Unknown Source) ~[na:1.8.0_91]
// Etc.
2017-05-10 14:58:05.889 DEBUG 928 --- [-nio-443-exec-4] o.apache.tomcat.util.threads.LimitLatch : Counting down[https-jsse-nio-443-exec-4] latch=1
2017-05-10 15:00:34.593 DEBUG 928 --- [-nio-443-exec-9] o.a.tomcat.util.net.SocketWrapperBase : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@58361212:org.apache.tomcat.util.net.SecureNioChannel@63c88911:java.nio.channels.SocketChannel[connected local=/... remote=/...]], Read from buffer: [0]
2017-05-10 15:00:34.593 DEBUG 928 --- [-nio-443-exec-9] o.apache.coyote.http11.Http11Processor : Error parsing HTTP request header
java.io.IOException: Unable to unwrap data, invalid status [CLOSED]
at org.apache.tomcat.util.net.SecureNioChannel.read(SecureNioChannel.java:604) ~[tomcat-embed-core-8.5.13.jar!/:8.5.13]
// Etc.
2017-05-10 15:00:34.593 DEBUG 928 --- [-nio-443-exec-9] o.apache.coyote.http11.Http11Processor : Socket: [org.apache.tomcat.util.net.NioEndpoint$NioSocketWrapper@58361212:org.apache.tomcat.util.net.SecureNioChannel@63c88911:java.nio.channels.SocketChannel[connected local=/... remote=/...]], Status in: [OPEN_READ], State out: [CLOSED]
2017-05-10 15:00:34.593 DEBUG 928 --- [-nio-443-exec-9] org.apache.tomcat.util.net.NioEndpoint : Failed to close socket
java.nio.channels.ClosedChannelException: null
at sun.nio.ch.SocketChannelImpl.ensureWriteOpen(Unknown Source) ~[na:1.8.0_91]
// Etc.
2017-05-10 15:00:34.593 DEBUG 928 --- [-nio-443-exec-9] o.apache.tomcat.util.threads.LimitLatch : Counting down[https-jsse-nio-443-exec-9] latch=1
根据我的理解,客户端似乎成功连接到服务器,但由于SSL / TLS错误导致文件传输期间中断连接,导致那些ClosedChannelException
服务器端。
我是否错误地使用了RestSharp?
RestRequest request = new RestRequest("path/to/uri", Method.PUT);
request.AddQueryParameter("myParam", myParam.ToString());
request.AddFile("myFile", "path/to/file", "multipart");
IRestResponse<MyResponse> response = myRestClient.Execute<MyResponse>(request);
此请求的Spring Boot代码:
@RequestMapping(method = RequestMethod.PUT, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public MyResponse replace(@RequestParam Integer myParam, @RequestParam MultipartFile myFile) {
// Etc.
Spring中默认不支持PUT
的{{1}}方法,但我创建了自己的multipart
来处理它,所以问题不在这里。
看起来问题只发生在一个地方,而且只在文件传输过程中发生。所有其他地方都可以正常工作,但仍有MultipartResolver
和EOFException
服务器端,即使它在客户端工作也是如此。
另一个不起眼的事情......它有时只会发生。有时候上传有效,有时候没有。
我不是SSL专家,所以我想知道它能做什么。
ClosedChannelException
?我对所有建议持开放态度,并会继续调查,并希望找到一些东西......
编辑2017-05-11
来自评论的精确度:
自我发布问题后检索到的信息:
ClosedChannelException
提供Windows NT 6.2.9200.0。根据{{3}},此内核版本对应于Windows 8或Server 2012,而不是10. 编辑确定,这是一种已知行为。请参阅Wikipedia和here。所以这与错误无关。System.Environment.OSVersion.VersionString
对象仅实例化一次,并在应用程序的任何位置使用。这可能是一个问题吗?调查仍在继续。