2015-04-07 90 views
0

我试图在Android客户端上使用自定义证书实现SSL连接。如果我尝试使用正常的Java程序连接到同一台服务器(我使用系统参数导入密钥存储区),那么一切正常。此外,如果我使用android方法连接到服务器,但没有https,它工作正常。但是,一旦我用HTTPS Android的方法(如下所示的方法),它给了我这个错误:套接字已关闭尝试sslException时出现异常

04-06 20:12:29.234: W/System.err(2328): java.net.SocketException: Socket is closed 
04-06 20:12:29.234: W/System.err(2328):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.checkOpen(OpenSSLSocketImpl.java:237) 
04-06 20:12:29.234: W/System.err(2328):  at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:250) 
04-06 20:12:29.234: W/System.err(2328):  at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:209) 
04-06 20:12:29.234: W/System.err(2328):  at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:478) 
04-06 20:12:29.234: W/System.err(2328):  at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:442) 
04-06 20:12:29.244: W/System.err(2328):  at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:290) 
04-06 20:12:29.244: W/System.err(2328):  at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:240) 
04-06 20:12:29.244: W/System.err(2328):  at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:81) 
04-06 20:12:29.244: W/System.err(2328):  at libcore.net.http.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:197) 
04-06 20:12:29.244: W/System.err(2328):  at libcore.net.http.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:281) 
04-06 20:12:29.244: W/System.err(2328):  at john.z.lead.utils.ServerRequest.get_response(ServerRequest.java:497) 
04-06 20:12:29.244: W/System.err(2328):  at john.z.lead.utils.ServerRequest.logout(ServerRequest.java:797) 
04-06 20:12:29.244: W/System.err(2328):  at john.z.lead.fragments.Logout_Fragment$1$1.run(Logout_Fragment.java:59) 
04-06 20:12:29.244: W/System.err(2328):  at java.lang.Thread.run(Thread.java:841) 

我使用的代码是:

public static JSONObject get_response(List<Parameter> params, 
     final String address) throws IOException, JSONException, LeadException { 
    // String body = "param1=" + URLEncoder.encode("value1", "UTF-8") + 
    // "&" + 
    // "param2=" + URLEncoder.encode("value2", "UTF-8"); 

    StringBuilder body = new StringBuilder(); 
    for (Parameter pa : params) { 
     body.append(pa.getKey() + "=" 
       + URLEncoder.encode(pa.getValue(), "UTF-8") + "&"); 
    } 
    try { 

     URL url = new URL(address); 

     HttpURLConnection connection = (HttpURLConnection) url 
       .openConnection(); 
     if (connection instanceof HttpsURLConnection) { 
      KeyStore trusted = KeyStore.getInstance("BKS"); 

      // Get the raw resource, which contains the keystore with 
      // your trusted certificates (root and any intermediate certs) 
      InputStream in = Datastore.getActiv().getResources() 
        .openRawResource(R.raw.truststore); 
      // Initialize the keystore with the provided trusted 
      // certificates 
      // Also provide the password of the keystore 
      trusted.load(in, "lead".toCharArray()); 

      // Create a TrustManager that trusts the CAs in our KeyStore 
      String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); 
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); 
      tmf.init(trusted); 



      // Create an SSLContext that uses our TrustManager 
      SSLContext context = SSLContext.getInstance("TLS"); 
      context.init(null, tmf.getTrustManagers(), null); 


      ((HttpsURLConnection) connection) 
        .setSSLSocketFactory(context.getSocketFactory()); 

     } 
     connection.setRequestMethod("POST"); 
     connection.setDoInput(true); 
     connection.setDoOutput(true); 
     connection.setUseCaches(false); 
     connection.setRequestProperty("Content-Type", 
       "application/x-www-form-urlencoded"); 
     connection.setRequestProperty("Content-Length", 
       String.valueOf(body.length())); 
     OutputStreamWriter writer = new OutputStreamWriter(
       connection.getOutputStream()); 

     writer.write(body.toString()); 
     writer.flush(); 
     BufferedReader reader = new BufferedReader(new InputStreamReader(
       connection.getInputStream())); 

     StringBuilder build = new StringBuilder(); 
     for (String line; (line = reader.readLine()) != null;) { 
      build.append(line); 
     } 

     writer.close(); 
     reader.close(); 

     return new JSONObject(build.toString()); 

    } catch (UnknownHostException | FileNotFoundException 
      | ConnectException e) { 
     Datastore.getActiv().runOnUiThread(new Runnable() { 

      @Override 
      public void run() { 
       Toast.makeText(
         Datastore.getActiv(), 
         "Konnte keine Verbindung zum Server (" 
           + address 
           + ") herstellen.\nBitte überprüfen Sie ihre Netzwerkverbindung und/oder\nkontaktieren Sie einen Administrator", 
         Toast.LENGTH_LONG).show(); 
       ; 

      } 

     }); 
     throw e; 
    } catch (KeyManagementException|KeyStoreException|NoSuchAlgorithmException|CertificateException e) { 
     MessageDialog.showMessageDialog(Datastore.getActiv(), "Es ist ein kritischer Fehler beim Herstellen der sicheren Verbindung aufgetreten"); 
     e.printStackTrace(); 
     throw new LeadException(LeadException.Errorcode.UNKNOWN); 
    } 

} 

回答

0

SocketException: socket is closed意味着关闭插座,然后继续使用它。

注意您不需要设置Content-Length标头。 HttpURLConnection会自动为你做。

+0

但我从来没有关闭过套接字。这个错误必须是由if-block内的东西引起的,因为如果url是非https,那么错误不会发生 – joz

相关问题