Android:使用SSL交换消息时出现问题

时间:2011-04-25 16:26:56

标签: java android ssl client

我一直在努力让客户通过SSL安全地与服务器通信。我创建了自己的自签名证书,似乎客户端可以使用证书连接到服务器,但客户端似乎从来没有从服务器获得响应。我尝试打印返回-1的content-length,并且实际内容似乎是一个空字符串,尽管预期会有一个简单的HTML'hello world'。

我做错了什么?

服务器:

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);
        }
    }
}

1 个答案:

答案 0 :(得分:0)

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