2011-04-25 2 views
2

SSL을 통해 안전하게 서버와 통신 할 수있는 클라이언트를 얻으려고했습니다. 내 자체 서명 인증서를 만들었고 클라이언트가 인증서를 사용하여 서버에 연결할 수 있지만 클라이언트가 서버에서 응답을받지 못하는 것처럼 보입니다. 간단한 HTML 'hello world'가 예상되지만 -1을 반환하는 content-length를 인쇄 해 보았습니다. 실제 내용은 빈 문자열로 보입니다.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

당신은 할 수 있습니다 t 응답을 보내기 전에 클라이언트에서 요청을 읽도록 서버 코드를 변경하십시오. 서버가 요청을 읽으려고 기다리는 동안 클라이언트가 차단 (및 시간 초과?) 될 수 있습니다.

관련 문제