java.net.SocketException:连接重置(SSL)

时间:2017-06-25 14:04:32

标签: java ssl connection-reset

我指的是这些问题:

我使用第二个问题的解决方案来处理所有建议的https协议:

System.getProperties().setProperty("https.protocols", "TLSv1.2,TLSv1.1,TLSv1,SSLv3");

完整代码:

/**
 * Opens HTTP/HTTPS and setup connection to given URL.
 *
 * @return prepared HttpURLConnection connection
 * @throws IOException in case URL is malformed or connection cannot be established
 */
public void openHttpUrlConnectionForGet() throws IOException {

  // Set Https protocols
  System.getProperties().setProperty("https.protocols", "TLSv1.2,TLSv1.1,TLSv1,SSLv3");

  // Create connection
  URL urlObject = new URL(location);
  HttpURLConnection conn;
  if (proxy != null) {
    InetSocketAddress adr = new InetSocketAddress(proxy.getPk().getAddress(), proxy.getPk().getPort());
    java.net.Proxy prx = new java.net.Proxy(java.net.Proxy.Type.HTTP, adr);
    conn = (HttpURLConnection) urlObject.openConnection(prx);
  } else {
    conn = (HttpURLConnection) urlObject.openConnection();
  }
  conn.setRequestMethod("GET");
  conn.setInstanceFollowRedirects(false);

  // Setup SSL factory
  if (conn instanceof HttpsURLConnection) {
    HttpsURLConnection httpsc = (HttpsURLConnection) conn;
    if (hostnameVerifier != null) {
      httpsc.setHostnameVerifier(hostnameVerifier);
    }
    if (trustManager != null) {
      try {
        SSLContext sc = SSLContext.getInstance("SSL");
        sc.init(null, new TrustManager[]{trustManager}, new java.security.SecureRandom());
        httpsc.setSSLSocketFactory(sc.getSocketFactory());
      } catch (KeyManagementException | NoSuchAlgorithmException e) {
        throw new RuntimeException("Cannot init HTTPS connection.", e);
      }
    }
  }

  // Configure timeouts
  conn.setConnectTimeout(connectTimeout);
  conn.setDefaultUseCaches(false);
  conn.setUseCaches(false);
  conn.setDoOutput(false);
  conn.setReadTimeout(readTimeout);

  // Check connection
  if (StringUtils.isEmpty(userAgent)) {
    throw new IllegalArgumentException("Cannot create HTTP(S) connection. User-Agent header is not set.");
  }
  if (StringUtils.isEmpty(accept)) {
    throw new IllegalArgumentException("Cannot create HTTP(S) connection. Accept header is not set.");
  }
  if (StringUtils.isEmpty(acceptLanguage)) {
    throw new IllegalArgumentException("Cannot create HTTP(S) connection. Accept-Language header is not set.");
  }
  if (StringUtils.isEmpty(acceptEncoding)) {
    throw new IllegalArgumentException("Cannot create HTTP(S) connection. Accept-Encoding header is not set.");
  }

  // Set headers
  conn.setRequestProperty("User-Agent", userAgent);
  conn.setRequestProperty("Accept", accept);
  conn.setRequestProperty("Accept-Language", acceptLanguage);
  conn.setRequestProperty("Accept-Encoding", acceptEncoding);
  conn.setRequestProperty("Connection", "keep-alive");
  conn.setRequestProperty("Upgrade-Insecure-Requests", "1");
  if (cookies != null) {
    conn.setRequestProperty("Cookie", cookies);
  }
  this.connection = conn;
}

但是我仍然收到:

java.net.SocketException: Connection reset
  at java.net.SocketInputStream.read(SocketInputStream.java:209)
  at java.net.SocketInputStream.read(SocketInputStream.java:141)
  at sun.security.ssl.InputRecord.readFully(InputRecord.java:465)
  at sun.security.ssl.InputRecord.read(InputRecord.java:503)
  at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:973)
  at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
  at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
  at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
  at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
  at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513)
  at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
  at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
  at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
  at cz.wm.common.net.HttpConnection.retrieveContent(HttpConnection.java:73)
  at cz.wm.agent.slave.job.search.AbstractSearchJob.getFinalURL(AbstractSearchJob.java:192)
  at cz.wm.common.job.AbstractAgentJob.run(AbstractAgentJob.java:46)
  at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54)
  at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
  at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180)
  at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294)
  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
  at java.lang.Thread.run(Thread.java:745)

例如,这是我可以通过浏览器打开但无法通过java HttpConnection打开的有问题的网站:

1 个答案:

答案 0 :(得分:3)

这些是需要TLS SNI扩展的所有站点,否则将失败。虽然Java 7+提供此扩展,但它并不是在所有情况下都添加它。来自https://javabreaks.blogspot.de/2015/12/java-ssl-handshake-with-server-name.html

  

每当提供自定义HostNameVerifier时,java 8都无法添加SNI扩展标头...

看起来你的代码确实设置了一个自定义HostNameVerifier,这通常是一个坏主意。因此,要么确保您的代码没有设置自定义HostNameVerifier,要么遵循提供的链接中列出的变通方法。