2017-06-04 201 views
0

我正在学习SSL通信,并且遇到了这个问题。我正在写一个简单的客户端,它试图与本地apache服务器握手。该服务器已启用https。我将服务器证书添加到所有可能的信任存储(也是该程序使用的jdk &中的一个)。但握手状态永远不会达到FINISHED。它一直处于NEED_TASK状态 第一次进入循环时,我得到一个sun.security.ssl.Handshaker $ DelegatedTask。此后,状态为NEED_TASK,任务为空。 。下面的代码我的理解错误\缺陷在哪里?SSL握手失败Java

注:我从下面的教程中的代码:

http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/JSSERefGuide.html#KRB

这是停留在NEED_TASK状态握手代码如下:

void doHandshake(SocketChannel socketChannel, SSLEngine engine, 
      ByteBuffer myNetData, ByteBuffer peerNetData) throws Exception { 

     // Create byte buffers to use for holding application data 
     int appBufferSize = engine.getSession().getApplicationBufferSize(); 
     ByteBuffer myAppData = ByteBuffer.allocate(appBufferSize); 
     ByteBuffer peerAppData = ByteBuffer.allocate(appBufferSize); 
     // Begin handshake 
     engine.beginHandshake(); 
     SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus(); 
     int i=0; 
     // Process handshaking message 
     while (hs != SSLEngineResult.HandshakeStatus.FINISHED && 
      hs != SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING) { 
      i++; 
      switch (hs) { 

      case NEED_UNWRAP: 
       // Receive handshaking data from peer 
       if (socketChannel.read(peerNetData) < 0) { 
        // The channel has reached end-of-stream 
       } 

       // Process incoming handshaking data 
       peerNetData.flip(); 
       SSLEngineResult res = engine.unwrap(peerNetData, peerAppData); 
       peerNetData.compact(); 
       hs = res.getHandshakeStatus(); 

       // Check status 
       switch (res.getStatus()) { 
       case OK : 
        // Handle OK status 
        break; 

       // Handle other status: BUFFER_UNDERFLOW, BUFFER_OVERFLOW, CLOSED 

       } 
       break; 

      case NEED_WRAP : 
       // Empty the local network packet buffer. 
       myNetData.clear(); 

       // Generate handshaking data 
       res = engine.wrap(myAppData, myNetData); 
       hs = res.getHandshakeStatus(); 

       // Check status 
       switch (res.getStatus()) { 
       case OK : 
        myNetData.flip(); 

        // Send the handshaking data to peer 
        while (myNetData.hasRemaining()) { 
         socketChannel.write(myNetData); 
        } 
        break; 

       // Handle other status: BUFFER_OVERFLOW, BUFFER_UNDERFLOW, CLOSED 

       } 
       break; 

      case NEED_TASK : 
       Runnable task =engine.getDelegatedTask(); 
       if(task!= null) { 
        //task.run(); 
        new Thread(task).start(); 
       }// Handle blocking tasks 

       break; 

      // Handle other status: // FINISHED or NOT_HANDSHAKING 

      } 
     } 
     // Processes after handshaking 

    } 

任何帮助,将不胜感激。

+0

你需要得到循环内的握手状态,否则它不可能在NEED_TASK情况发生变化,也许别人的好。状态将保持NEED_TASK状态,直到任务完成。在一个单独的线程中处理任务确实非常复杂。你可能会更好地运行它,直到你至少工作。通过循环写入,你正在做类似的事情。解决这两个问题都需要与一个'Selector'集成,这也是非常重要的。 – EJP

+0

@EJP这个任务应该做什么?这个任务被卡住了,因为我没有将服务器证书添加到任何信任存储?我只想达到握手的完成状态。那是我现在唯一的目标。这个选择器概念有一些教程或起始页吗? –

+0

它与信任库有关,不知道是什么。 – EJP

回答

0

问题是我对engine.getHandShakeStatus()方法的不完全理解。

我改变了上面的代码

case NEED_TASK : 
      Runnable task =engine.getDelegatedTask(); 
      if(task!= null) { 
       //task.run(); 
       new Thread(task).start(); 
      } 
      hs = engine.getHandshakeStatus(); 
      break; 

而现在完成了握手

+0

你需要在循环中每次都做,而不只是在这里。 – EJP

+0

@EJP ...是的。现在我明白你的意思了。我想如果你可以把答案放在同一位置,我可以将其标记为答案。 –