Java Http网络问题

5

我正在尝试实现最简单的HTTPS通信程序。网络上有很多例子,但我无法成功运行它们。
这是一个例子:

public class ReadHttpsURL1 {
   static final int HTTPS_PORT = 443; 

   public static void main(String argv[]) throws Exception {
       String url = "www.sun.com";
       System.setProperty("java.net.useSystemProxies", "true");

      SocketFactory factory = SSLSocketFactory.getDefault(); 

      Socket socket = factory.createSocket(url, HTTPS_PORT); 

      BufferedWriter out = new BufferedWriter(new 
            OutputStreamWriter(socket.getOutputStream()));
      BufferedReader in = new BufferedReader(
        new InputStreamReader(socket.getInputStream()));
      out.write("GET / HTTP/1.0\n\n");
      out.flush();

      String line;
      StringBuffer sb = new StringBuffer();
      while((line = in.readLine()) != null) {
         sb.append(line);
      }
      out.close();
      in.close();
      System.out.println(sb.toString());
   }
}

它会在大约一分钟左右挂起(我认为是由于服务器端超时),然后出现错误。挂起在

Socket socket = factory.createSocket(url, HTTPS_PORT); 

错误是

Exception in thread "main" java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(Unknown Source)
    at java.net.SocksSocketImpl.readSocksReply(Unknown Source)
    at java.net.SocksSocketImpl.connect(Unknown Source)
    at java.net.Socket.connect(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.connect(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.<init>(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketFactoryImpl.createSocket(Unknown Source)
    at com.sun.ex1.ReadHttpsURL1.main(ReadHttpsURL1.java:20)

这是第二个例子:
public class HttpsTest {

    public static void main(String[] args) throws MalformedURLException, IOException {
        System.setProperty("java.net.useSystemProxies", "true");

        URL url = new URL("https://www.sun.com");
        URLConnection con = url.openConnection();
        con.setAllowUserInteraction(true);
        InputStream is = new BufferedInputStream(con.getInputStream());
        for (int b = is.read(); b >= 0; b = is.read()) {
            System.out.write(b);
        }
    }
}

只需抛出此异常:

Exception in thread "main" javax.net.ssl.SSLKeyException: RSA premaster secret error
    at com.sun.net.ssl.internal.ssl.RSAClientKeyExchange.<init>(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverHelloDone(Unknown Source)
    at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Unknown Source)
    at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(Unknown Source)
    at sun.net.www.protocol.https.HttpsClient.afterConnect(Unknown Source)
    at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(Unknown Source)
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown Source)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(Unknown Source)
    at HttpsTest.main(HttpsTest.java:16)
Caused by: java.security.NoSuchAlgorithmException: SunTlsRsaPremasterSecret KeyGenerator not available
    at javax.crypto.KeyGenerator.<init>(DashoA13*..)
    at javax.crypto.KeyGenerator.getInstance(DashoA13*..)
    at com.sun.net.ssl.internal.ssl.JsseJce.getKeyGenerator(Unknown Source)
    ... 14 more

我已经阅读了一些NoSuchAlgorithmException的相关信息。这似乎与sunjce_provider.jar有关。
我尝试了不同的变体来包含这个文件在类路径中,甚至将应用程序的依赖性附加到这个jar(可以确定这个jar已经存在于类路径中)
HTTPS URL是活动URL。代理设置有效(否则会引发不同的连接异常)。
java版本"1.6.0_23"
这些错误是否相关?
有什么想法如何解决?
感谢您的帮助!
3个回答

2
我在Eclipse IDE上输入了以上代码,它可以正常运行。 我认为你可能会遇到的一个问题是代理服务器。 下面是响应内容:
HTTP/1.1 301 Moved Permanently
Server: Sun-Java-System-Web-Server/7.0
Date: Fri, 25 Feb 2011 11:52:30 GMT
P3p: policyref="http://www.sun.com/p3p/Sun_P3P_Policy.xml", CP="CAO DSP COR CUR ADMa DEVa TAIa PSAa PSDa CONi TELi OUR  SAMi PUBi IND PHY ONL PUR COM NAV INT DEM CNT STA POL PRE GOV"Location: http://www.oracle.com/us/sun
Content-length: 0
Connection: close

我从你的代码中修改的只有这一段代码:
System.setProperty("java.net.useSystemProxies", "false");

仅是我的猜测:
  • 你所在的网络实际上没有使用代理,但你却打开了代理;或者
  • 你的代理不支持HTTPS;或者
  • 你的用户的代理HTTPS支持已被禁用(无论是有意还是无意)。
曾经提到过:

如果您不打算编写低级库……那么考虑使用[Apache的Http Components][1]如何?

[1]: http://hc.apache.org/index.html


最初的想法是实现最简单的应用程序,以自动将安全证书导入到Java公共存储中。我发现了使用套接字的实现,但似乎对我来说无效。于是我开始挖掘一下。http://www.technojeeves.com/joomla/index.php/free/46-java-cert - Mike

0
你是自己写这段代码还是从其他地方复制来的?我问这个问题是因为这不是我通常建立HTTPS连接的方式。在测试HTTPS时,我会首先找到一个能够响应HTTPS请求的服务器。www.sun.com将重定向到Oracle页面,虽然这仍然有效,但可能不是你想要的。
对于第一个问题,我不能100%确定,但我怀疑你可能正在遭受阻塞读取或写入。调试可能会有所帮助。
我曾经看到过类似的堆栈跟踪,那是当Java 5和6的JCE类混合在一起时,Java版本无法处理的情况。在HttpsTest中相同的代码“对我有用”。

我从网络上获取了代码。我还有几个例子也不起作用。我已经发布了最简单的一个。我没有5和6 Java,但我已经安装了JRE并且必须安装JDK,所以我在不同的位置拥有相同版本的JRE和JDK。另外URL不是问题,我尝试了不同的URL而没有重定向,例如https://encrypted.google.com。这肯定不是编程问题,而是一种配置问题。我正在努力找出我缺少的JVM配置。 - Mike
人们也争论这是Java 6的问题,而在Java 5中并不是一个问题。http://forums.oracle.com/forums/thread.jspa?messageID=6412248 - Mike
我会尝试以下几种方法:寻找备选的SSL提供商(检查bouncycastle.org),复制到jre/lib/ext并在jre/lib/security/security.properties中进行配置,或者备份jre/lib/ext/sunjce_provider.jar并替换成他人的副本。 - David O'Meara
在完全卸载JDK和JRE后,安装新的JDK 1.6.0_24(JDK安装完成后,JRE会自动安装),javax.net.ssl.SSLKeyException: RSA premaster secret error问题得到了解决。但我还没有弄清楚这种情况下是什么原因导致了问题。 - Mike
套接字问题是由代理引起的。我错误地得出结论,如果我没有得到java.net.ConnectException: Connection refused: connect(如果根本没有配置Java使用代理),那么代理不应该引起问题。在“访客网络”中(完全没有代理),应用程序似乎正常工作。事实证明,代理对每个协议有不同的配置,并且我的公司政策不赞成原始套接字连接。 - Mike

0
套接字问题是由代理引起的。我错误地得出结论,如果我没有收到“java.net.ConnectException:Connection refused:connect”(在没有配置代理的情况下),代理不应该引起问题。在“访客网络”(没有代理)中,应用程序似乎正常工作。事实证明,代理为每个协议配置不同的配置,并且我的公司政策不赞成原始套接字连接。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接