java - 如何在android客户端和自定义java服务器之间使用SSL套接字

标签 java android security ssl

我正在尝试编写一个通过安全连接 (SSL/TLS) 与 Java PC 服务器通信的 Android 应用程序但是 android (3.2) 设备上的客户端代码会在 SSL 或 TLS 握手时停止。 以下为客户端通信代码:

public class ClientCommunicationManager implements Runnable{
    /**
     * Application context
    */
    private Context context;
    /**
     * Host string
    */
    private String host;
    /**
    * port number
    */
    private int port;
      /**
       * Report Recieved Listeners vector
       */
      private Vector<ReportRecievedListener> rrListeners;
      /**
       * Connection to the client
       */
      private DataInputStream din;

      /**
       * Connection to the client
       */
      private DataOutputStream dout;

      /**
       * KeyStore for storing our public/private key pair
       */
      private KeyStore clientKeyStore;

      /**
       * KeyStore for storing the server's public key
       */
      private KeyStore serverKeyStore;

      /**
       * Used to generate a SocketFactory
       */
      private SSLContext sslContext;

      /**
       * A list of visible postings
       */
      private Set postings = new HashSet();

      /**
       * Passphrase for accessing our authentication keystore
       */
      static private final String passphrase = "a1n2d3r4o5i6d";

      /**
       * A source of secure random numbers
       */
      static private SecureRandom secureRandom;

      public ClientCommunicationManager( String host, int port,Context context ) {
          this.context = context;
          this.host = host;
          this.port = port;

          rrListeners = new Vector<ReportRecievedListener>();

          secureRandom = new SecureRandom();
          secureRandom.nextInt();      




      }

      public void registerRRListener(ReportRecievedListener listener){
          rrListeners.add(listener);
      }

      private void setupServerKeystore() throws GeneralSecurityException, IOException {
        serverKeyStore = KeyStore.getInstance( "BKS" );

        serverKeyStore.load( context.getResources().openRawResource(R.raw.serverbks), 
                            "public".toCharArray() );
      }

      private void setupClientKeyStore() throws GeneralSecurityException, IOException {
        clientKeyStore = KeyStore.getInstance( "BKS" );
        clientKeyStore.load( context.getResources().openRawResource(R.raw.clientbks),
                           passphrase.toCharArray() );
      }

      private void setupSSLContext() throws GeneralSecurityException, IOException {
        TrustManagerFactory tmf =       TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        tmf.init( serverKeyStore );

        KeyManagerFactory kmf =     KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        kmf.init( clientKeyStore, passphrase.toCharArray() );

        sslContext = SSLContext.getInstance( "SSL" );
        sslContext.init( kmf.getKeyManagers(),
                         tmf.getTrustManagers(),
                         secureRandom );
      }

      public void connect() {
         new Thread(new Runnable() {

            public void run() {
                try {
                    setupServerKeystore();
                    setupClientKeyStore();
                    setupSSLContext();
                } catch (GeneralSecurityException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (IOException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                }




               SSLSocketFactory sf = sslContext.getSocketFactory();


               SSLSocket socket= null;
               InputStream in = null;
               OutputStream out = null;

            try {
                 socket = (SSLSocket)sf.createSocket( host, port );
                 socket.setUseClientMode(true); 

                 socket.startHandshake();

                 in = socket.getInputStream();
                 out = socket.getOutputStream();
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }



               din = new DataInputStream( in );
               dout = new DataOutputStream( out );

               if(socket!=null)
                  new Thread( this ).start();

            }
        }).start();

      }



      public void run() {
          boolean isConnected = true;
        try {
          while (isConnected) {
            String msg = din.readUTF();
            if(msg.equals("END"))
                isConnected = false;
            else
                fireReportRecievedEvent(new ReportRecievedEvent(msg));


          }
        } catch( IOException ie ) {
          ie.printStackTrace();
        }
      }

     private void fireReportRecievedEvent(ReportRecievedEvent event){
         for(ReportRecievedListener listener : rrListeners){
             listener.onReportRecieved(event);
         }
     }


}

服务器代码如下:

public class CommunicationManager implements Runnable{

  private int port = Constants.SERVER_PORT;
  private HashSet<ConnectionProcessor> connections = new     HashSet<ConnectionProcessor>();
  private KeyStore clientKeyStore;
  private KeyStore serverKeyStore;
  private SSLContext sslContext;
  static private SecureRandom secureRandom;
  private boolean running;
  private SSLServerSocket ss=null;

  private static CommunicationManager instance=null;



private CommunicationManager(){

}

public static CommunicationManager getInstance(){
    if(instance == null){
        instance = new CommunicationManager();
    }

    return instance;
}


public int getSecureRandom(){
    SecureRandom securerandom = new SecureRandom();
    return securerandom.nextInt();

}



public boolean isRunning() {
    return running;
}



public void setRunning(boolean running) {
    this.running = running;
}

public void startServer(){
    if(!isRunning()){
        setRunning(true);
        new Thread(this).start();
    }

}

public void stopServer(){
    setRunning(false);
    for(ConnectionProcessor cp : connections){
        cp.close();
    }

    try {
        if(ss!=null)
            ss.close();
    } catch (IOException e) {

        e.printStackTrace();
    }

}



private void setupClientKeyStore() throws GeneralSecurityException, IOException {
    clientKeyStore = KeyStore.getInstance( "JKS" );
    clientKeyStore.load( new FileInputStream( "resources/client.public" ),
                       "public".toCharArray() );
  }

  private void setupServerKeystore() throws GeneralSecurityException, IOException {
    serverKeyStore = KeyStore.getInstance( "JKS" );
    serverKeyStore.load( new FileInputStream( "resources/server.private" ),
                        Constants.SERVER_KEYSTORE_PWD.toCharArray() );
  }

  private void setupSSLContext() throws GeneralSecurityException, IOException {
    TrustManagerFactory tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() );
    tmf.init( clientKeyStore );

    KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm() );
    kmf.init( serverKeyStore, Constants.SERVER_KEYSTORE_PWD.toCharArray() );

    sslContext = SSLContext.getInstance( "TLS" );
    sslContext.init( kmf.getKeyManagers(),
                     tmf.getTrustManagers(),
                     secureRandom );
  }



  @Override
  public void run() {


      try {
          setupClientKeyStore();
          setupServerKeystore();  
          setupSSLContext();
    } catch (GeneralSecurityException | IOException e) {
        e.printStackTrace();
    }

      SSLServerSocketFactory sf = sslContext.getServerSocketFactory();

      try {
        ss = (SSLServerSocket)sf.createServerSocket( port );
    } catch (IOException e) {

        e.printStackTrace();
    }

      // Require client authorization
      ss.setNeedClientAuth( true );


      System.out.println( "Listening on port "+port+"..." );
      while (isRunning()) {
        Socket socket=null;
        try {
            socket = ss.accept();
        } catch (IOException e) {

            if(e.getClass() == SocketException.class){
                System.out.print("accept() threw SocketException because of close\n");
            }
        }
        if(socket!=null && socket.isConnected()){
            System.out.println( "Got connection from "+socket );

            ConnectionProcessor cp = new ConnectionProcessor( this, socket );
            connections.add( cp );
        }

      }






     closeServer();
  }

  private void closeServer() {
    for(ConnectionProcessor cp : connections){
        cp.close();
    }

    try {
        ss.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

}

/**
   * Remove a connection that has been closed from our set
   * of open connections
   */
  public void removeConnection( ConnectionProcessor cp ) {
    connections.remove( cp );
  }

  /**
   * Return an iteration over open connections
   */
  public Iterator getConnections() {
    return connections.iterator();
  }
  /**
   * Broadcast a report over all connections
   */
  public void broadcastReport(String report){
      for(ConnectionProcessor cp : connections){
          cp.send(report);
      }
  }
  /**
   * Broadcast a report over all connections using a new thread
   */

public void broadcastOnThread(final String report) {
    Thread t = new Thread(new Runnable() {

        @Override
        public void run() {
            if(isRunning())
                broadcastReport(report);    

        }
    }) ;

    t.start();
}

 /**
   * recieve a new report to be broadcasted
   */
public void acceptReport(String report_string) {
    broadcastOnThread(report_string);

}





}

任何帮助或见解将不胜感激。谢谢。

最佳答案

问题是(还)没有数据被交换,所以握手从未完成。

关于java - 如何在android客户端和自定义java服务器之间使用SSL套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13440664/

相关文章:

android - 如何隐藏工具栏中的菜单项(查看寻呼机,嵌套 fragment )

Python:使用 chroot 和 chjail 保护不受信任的脚本/子进程?

java - 如何在 PHP 中重现 java MessageDigest SHA-256 哈希?

excel - 通过使用宏防止 ThisWorkbook 中的隐藏工作表可见并从另一个工作簿运行

java - Maven:为什么父pom中声明的依赖项不被子pom继承?

java - DropWizard 不使用 LogBack 并支持我的 log4j.properties

java - 我如何将对象传递给 Javafx 类以便按程序创建 GUI?

Android 直播视频 - 音频不工作

java - 编辑文本自动计算

java - EpGap 可以取的最大值是多少?