2011-04-25 28 views
2

我一直试图让客户端通过SSL安全地与服务器通信。我创建了自己的自签名证书,看起来客户端可以使用证书连接到服务器,但客户端似乎从未从服务器获得响应。我试着打印返回-1的内容长度,实际的内容似乎是一个空字符串,尽管预计会有一个简单的HTML'hello world'。Android:问题与SSL交换消息

我在做什么错?

服务器:

public class SSLServer { 
    public static void main(String[] args) { 
     String ksName = "key.jks"; 
     char ksPass[] = "password".toCharArray(); 
     char ctPass[] = "password".toCharArray(); 
     try { 
     KeyStore ks = KeyStore.getInstance("JKS"); 
     ks.load(new FileInputStream(ksName), ksPass); 
     KeyManagerFactory kmf = 
     KeyManagerFactory.getInstance("SunX509"); 

     kmf.init(ks, ctPass); 
     SSLContext sc = SSLContext.getInstance("TLS"); 
     sc.init(kmf.getKeyManagers(), null, null); 
     SSLServerSocketFactory ssf = sc.getServerSocketFactory(); 
     SSLServerSocket s 
      = (SSLServerSocket) ssf.createServerSocket(8888); 
     System.out.println("Server started:"); 
     // Listening to the port 
     SSLSocket c = (SSLSocket) s.accept(); 
     BufferedWriter w = new BufferedWriter(
      new OutputStreamWriter(c.getOutputStream())); 

     w.write("HTTP/1.0 200 OK"); 
     w.write("Content-Type: text/html"); 
     w.write("<html><body>Hello world!</body></html>"); 
     w.flush(); 
     w.close(); 
     c.close(); 
     } catch (Exception e) { 
     e.printStackTrace(); 
     } 
    } 

} 

客户:

public class TestSSLActivity extends Activity { 
    /** Called when the activity is first created. */ 
    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     // Instantiate the custom HttpClient 
     DefaultHttpClient client = new MyHttpClient(getApplicationContext()); 
     HttpGet get = new HttpGet("https://192.168.15.195:8888"); 
     // Execute the GET call and obtain the response 
     HttpResponse getResponse; 
     try { 
      getResponse = client.execute(get); 
      HttpEntity responseEntity = getResponse.getEntity(); 
      Log.i("Connection",responseEntity.getContentLength()+""); 
      BufferedReader reader = new BufferedReader(new InputStreamReader(responseEntity.getContent(), "UTF-8")); 
      StringBuilder builder = new StringBuilder(); 

      for (String line = null; (line = reader.readLine()) != null;) { 
       builder.append(line).append("\n"); 
      } 
      Log.i("Connection","build: "+builder.toString()); 


     } catch (Exception e) { 
      Log.i("Connection",e.getMessage()); 
     } 
    } 

定义HTTP客户端:

public class MyHttpClient extends DefaultHttpClient { 

    final Context context; 

    public MyHttpClient(Context context) { 
     this.context = context; 
    } 

    @Override 
    protected ClientConnectionManager createClientConnectionManager() { 
     SchemeRegistry registry = new SchemeRegistry(); 
     registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); 
     // Register for port 443 our SSLSocketFactory with our keystore 
     // to the ConnectionManager 
     registry.register(new Scheme("https", newSslSocketFactory(), 443)); 
     return new SingleClientConnManager(getParams(), registry); 
    } 

    private SSLSocketFactory newSslSocketFactory() { 
     try { 
      // Get an instance of the Bouncy Castle KeyStore format 
      KeyStore trusted = KeyStore.getInstance("BKS"); 
      // Get the raw resource, which contains the keystore with 
      // your trusted certificates (root and any intermediate certs) 
      InputStream in = context.getResources().openRawResource(R.raw.key); 
      try { 
       // Initialize the keystore with the provided trusted certificates 
       // Also provide the password of the keystore 
       trusted.load(in, "password".toCharArray()); 
      } finally { 
       in.close(); 
      } 
      // Pass the keystore to the SSLSocketFactory. The factory is responsible 
      // for the verification of the server certificate. 
      SSLSocketFactory sf = new SSLSocketFactory(trusted); 
      // Hostname verification from certificate 
      // http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d4e506 
      sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER); 
      return sf; 
     } catch (Exception e) { 
      throw new AssertionError(e); 
     } 
    } 
} 

回答

0

您可能要牛逼o在发送响应之前更改服务器代码以从客户端读取请求。可能是客户端阻塞(然后超时?)等待服务器读取请求。