Android SSL HttpGet(无对等证书)错误或(连接被对等closures)错误

我正在尝试做一个简单的HttpGet来读取一个网页。 我有这个在iOS上工作,并通过HTTP在Android上工作,但不是https

该url是一个内部networkingIP和自定义端口,所以我可以用这样的http://ipaddress:port/MyPage.html使用http://ipaddress:port/MyPage.html

 HttpClient httpclient = new DefaultHttpClient(httpParameters); HttpResponse response; String responseString = null; try { // Try connection HttpGet get = new HttpGet(params[0].path); get.addHeader("Authorization", "Basic " + Base64.encodeBytes(new String(params[0].username + ":" + params[0].password) .getBytes())); response = httpclient.execute(get); StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() == HttpStatus.SC_OK) { ByteArrayOutputStream out = new ByteArrayOutputStream(); response.getEntity().writeTo(out); out.close(); responseString = out.toString(); } else { // Closes the connection. response.getEntity().getContent().close(); throw new IOException(statusLine.getReasonPhrase()); } } catch (ClientProtocolException e) { Log.e(TAG, "ClientProtocolException"); this.e = e; } catch (IOException e) { Log.e(TAG, "IOException"); this.e = e; } return responseString; 

当我尝试使用https时,我得到No peer certificate错误。 所以我已经尝试使用此代码: HttpClient httpclient = new DefaultHttpClient(httpParameters);

 private HttpClient createHttpClient() { try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.DEFAULT_CONTENT_CHARSET); HttpProtocolParams.setUseExpectContinue(params, true); SchemeRegistry schReg = new SchemeRegistry(); schReg.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); schReg.register(new Scheme("https", sf, 8080)); ClientConnectionManager conMgr = new ThreadSafeClientConnManager(params, schReg); return new DefaultHttpClient(conMgr, params); } catch (Exception e) { return new DefaultHttpClient(); } } 

但是这给了我一个Connection closed by peer错误Connection closed by peerConnection closed by peer

我究竟做错了什么? 我可以安全地忽略证书,因为它是一个内部networking,具有自签名证书,但是我无法控制vert,我的应用程序的用户可能有不同的证书,所以我真的需要自动接受或绕过它。

谢谢

编辑——————————

在尝试我的名字之后,回答如下:我build立了一个CustomX509TrustManager类,然后使用它创build一个自定义的HttpClient:

 private HttpClient sslClient(HttpClient client) { try { CustomX509TrustManager tm = new CustomX509TrustManager(); SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, new TrustManager[] { tm }, null); SSLSocketFactory ssf = new MySSLSocketFactory(ctx); ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); ClientConnectionManager ccm = client.getConnectionManager(); SchemeRegistry sr = ccm.getSchemeRegistry(); sr.register(new Scheme("https", ssf, 8080)); return new DefaultHttpClient(ccm, client.getParams()); } catch (Exception ex) { return null; } } 

最后使用这个HttpClient是这样的:

 private class httpGETTask extends AsyncTask<GetParams, Void, String> { private Exception e = null; @Override protected String doInBackground(GetParams... params) { // Set connection parameters HttpParams httpParameters = new BasicHttpParams(); int timeoutConnection = 15000; HttpConnectionParams.setConnectionTimeout(httpParameters, timeoutConnection); int timeoutSocket = 15000; HttpConnectionParams.setSoTimeout(httpParameters, timeoutSocket); Log.v(TAG, params[0].path); HttpClient httpclient = new DefaultHttpClient(httpParameters); httpclient = sslClient(httpclient); HttpResponse response; String responseString = null; try { // Try connection HttpGet get = new HttpGet(params[0].path); get.addHeader("Authorization", "Basic " + Base64.encodeBytes(new String(params[0].username + ":" + params[0].password) .getBytes())); response = httpclient.execute(get); StatusLine statusLine = response.getStatusLine(); if (statusLine.getStatusCode() == HttpStatus.SC_OK) { ByteArrayOutputStream out = new ByteArrayOutputStream(); response.getEntity().writeTo(out); out.close(); responseString = out.toString(); } else { // Closes the connection. response.getEntity().getContent().close(); throw new IOException(statusLine.getReasonPhrase()); } } catch (ClientProtocolException e) { Log.e(TAG, "ClientProtocolException"); this.e = e; } catch (IOException e) { Log.e(TAG, "IOException"); this.e = e; } return responseString; 

logging的path格式为https://ipaddress:8080/Page.html但是,我得到一个Connection closed By Peer错误:

05-24 08:20:32.500:E / ConnectionHelper(1129):IOException 05-24 08:20:32.550:E / ConnectionHelper(1129):exception加载内容05-24 08:20:32.550:E / ConnectionHelper(1129 ):javax.net.ssl.SSLException:由对等closures的连接05-24 08:20:32.550:E / ConnectionHelper(1129):at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method) 05-24 08:20:32.550:E / ConnectionHelper(1129):at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410)05-24 08:20:32.550:E / ConnectionHelper(1129):在org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl $ SSLInputStream。(OpenSSLSocketImpl.java:643)05-24 08:20:32.550:E / ConnectionHelper(1129):在org.apache。 (OpenSSLsocketImpl.java:614)05-24 08:20:32.550:E / ConnectionHelper(1129):在org.apache.http.impl.io.SocketInputBuffer。(SocketInputBuffer。 java:70)05-24 08:20:32.550:E / ConnectionHelper(1129):at org.apache.http.impl.Soc ketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83)05-24 08:20:32.550:E / ConnectionHelper(1129):at org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170)05-24 08:20:32.550:E / ConnectionHelper(1129):at org.apache.http.impl.SocketHttpClientConnection.bind(SocketHttpClientConnection.java:106)05-24 08:20:32.550:E / ConnectionHelper(1129):at org .apache.http.impl.conn.DefaultClientConnection.openCompleted(DefaultClientConnection.java:129)05-24 08:20:32.550:E / ConnectionHelper(1129):at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection( 0512 08:20:32.550:E / ConnectionHelper(1129):at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)05-24 08:20: 32.550:E / ConnectionHelper(1129):at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)05-24 08:20:32.550:E / ConnectionHelper 1129):at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:360)05-24 08:20:32.550:E / ConnectionHelper(1129):at org.apache.http.impl.client .AbstractHttpClient.execute(AbstractHttpClient.java:555)05-24 08:20:32.550:E / ConnectionHelper(1129):at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)05- 24 08:20:32.550:E / ConnectionHelper(1129):at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)05-24 08:20:32.550:E / ConnectionHelper(1129) :at com.d_apps.my_app.connection_helpers.ConnectionHelper $ httpGETTask.doInBackground(ConnectionHelper.java:114)

Solutions Collecting From Web of "Android SSL HttpGet(无对等证书)错误或(连接被对等closures)错误"

以下来源应该解决您的问题。

 import android.app.Activity; import android.widget.EditText; import android.os.Bundle; import org.apache.http.HttpResponse; import org.apache.http.Header import java.io.InputStream; import java.io.BufferedReader; import java.io.InputStreamReader; import android.util.Log; import android.view.Menu; public class MainActivity extends Activity { private EditText text; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); text = (EditText) findViewById(R.id.editText1); connect(); } private void connect(){ try { DataLoader dl = new DataLoader(); String url = "https://IpAddress"; HttpResponse response = dl.secureLoadData(url); StringBuilder sb = new StringBuilder(); sb.append("HEADERS:\n\n"); Header[] headers = response.getAllHeaders(); for (int i = 0; i < headers.length; i++) { Header h = headers[i]; sb.append(h.getName()).append(":\t").append(h.getValue()).append("\n"); } InputStream is = response.getEntity().getContent(); StringBuilder out = new StringBuilder(); BufferedReader br = new BufferedReader(new InputStreamReader(is)); for (String line = br.readLine(); line != null; line = br.readLine()) out.append(line); br.close(); sb.append("\n\nCONTENT:\n\n").append(out.toString()); Log.i("response", sb.toString()); text.setText(sb.toString()); } catch (Exception e) { e.printStackTrace(); } } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } } import android.app.Application; import android.content.Context; import java.io.InputStream; public class MeaApplication extends Application { private static Context context; @Override public void onCreate() { super.onCreate(); MeaApplication.context = getApplicationContext(); } public static Context getAppContext() { return MeaApplication.context; } public static InputStream loadCertAsInputStream() { return MeaApplication.context.getResources().openRawResource( R.raw.meacert); } } import org.apache.http.conn.ssl.SSLSocketFactory; import javax.net.ssl.SSLContext; import java.security.KeyStore; import java.security.NoSuchAlgorithmException; import java.security.KeyManagementException; import java.security.KeyStoreException; import java.security.UnrecoverableKeyException; import javax.net.ssl.TrustManager; import java.net.Socket; import java.io.IOException; import java.net.UnknownHostException; /** * Taken from: http://janis.peisenieks.lv/en/76/english-making-an-ssl-connection-via-android/ * */ public class CustomSSLSocketFactory extends SSLSocketFactory { SSLContext sslContext = SSLContext.getInstance("TLS"); public CustomSSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(truststore); TrustManager tm = new CustomX509TrustManager(); sslContext.init(null, new TrustManager[] { tm }, null); } public CustomSSLSocketFactory(SSLContext context) throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException { super(null); sslContext = context; } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); } @Override public Socket createSocket() throws IOException { return sslContext.getSocketFactory().createSocket(); } } import javax.net.ssl.X509TrustManager; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.io.IOException; import java.io.InputStream; import java.security.cert.CertificateFactory; public class CustomX509TrustManager implements X509TrustManager { @Override public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } @Override public void checkServerTrusted(java.security.cert.X509Certificate[] certs, String authType) throws CertificateException { // Here you can verify the servers certificate. (eg against one which is stored on mobile device) // InputStream inStream = null; // try { // inStream = MeaApplication.loadCertAsInputStream(); // CertificateFactory cf = CertificateFactory.getInstance("X.509"); // X509Certificate ca = (X509Certificate) // cf.generateCertificate(inStream); // inStream.close(); // // for (X509Certificate cert : certs) { // // Verifing by public key // cert.verify(ca.getPublicKey()); // } // } catch (Exception e) { // throw new IllegalArgumentException("Untrusted Certificate!"); // } finally { // try { // inStream.close(); // } catch (IOException e) { // e.printStackTrace(); // } // } } public X509Certificate[] getAcceptedIssuers() { return null; } } import org.apache.http.HttpResponse; import org.apache.http.client.ClientProtocolException; import java.io.IOException; import java.security.NoSuchAlgorithmException; import java.security.KeyManagementException; import java.net.URISyntaxException; import java.security.KeyStoreException; import java.security.UnrecoverableKeyException; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import java.security.SecureRandom; import org.apache.http.client.HttpClient; import org.apache.http.impl.client.DefaultHttpClient; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.scheme.Scheme; import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.client.methods.HttpGet; public class DataLoader { public HttpResponse secureLoadData(String url) throws ClientProtocolException, IOException, NoSuchAlgorithmException, KeyManagementException, URISyntaxException, KeyStoreException, UnrecoverableKeyException { SSLContext ctx = SSLContext.getInstance("TLS"); ctx.init(null, new TrustManager[] { new CustomX509TrustManager() }, new SecureRandom()); HttpClient client = new DefaultHttpClient(); SSLSocketFactory ssf = new CustomSSLSocketFactory(ctx); ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); ClientConnectionManager ccm = client.getConnectionManager(); SchemeRegistry sr = ccm.getSchemeRegistry(); sr.register(new Scheme("https", ssf, 443)); DefaultHttpClient sslClient = new DefaultHttpClient(ccm, client.getParams()); HttpGet get = new HttpGet(new URI(url)); HttpResponse response = sslClient.execute(get); return response; } } 

如果您使用的是“不受信任”(开发人员)证书,那么下面是解决scheme。 我们需要信任所有的证书,下面是这样做的方法。 对于可信任的证书而言,它不起作用,我们只需要将http更改为https即可。

这是不可信证书的解决scheme。

在HttpClient方式下,你应该从org.apache.http.conn.ssl.SSLSocketFactory创build一个自定义类,而不是一个org.apache.http.conn.ssl.SSLSocketFactory本身

示例就像…

 import java.io.IOException; import java.net.Socket; import java.net.UnknownHostException; import java.security.KeyManagementException; import java.security.KeyStore; import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.UnrecoverableKeyException; import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManager; import javax.net.ssl.X509TrustManager; import org.apache.http.conn.ssl.SSLSocketFactory; public class MySSLSocketFactory extends SSLSocketFactory { SSLContext sslContext = SSLContext.getInstance("TLS"); public MySSLSocketFactory(KeyStore truststore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException { super(truststore); TrustManager tm = new X509TrustManager() { public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { } public X509Certificate[] getAcceptedIssuers() { return null; } }; sslContext.init(null, new TrustManager[] { tm }, null); } @Override public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException { return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose); } @Override public Socket createSocket() throws IOException { return sslContext.getSocketFactory().createSocket(); } } 

并在创buildHttpClient的实例时使用这个类。

 public HttpClient getNewHttpClient() { try { KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); trustStore.load(null, null); SSLSocketFactory sf = new MySSLSocketFactory(trustStore); sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER); HttpParams params = new BasicHttpParams(); HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1); HttpProtocolParams.setContentCharset(params, HTTP.UTF_8); SchemeRegistry registry = new SchemeRegistry(); registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); registry.register(new Scheme("https", sf, 443)); ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry); return new DefaultHttpClient(ccm, params); } catch (Exception e) { return new DefaultHttpClient(); } } 

检查您的设备的date。 你可能已经改变了不同的一年。 孩子们使用我的手机时,我经常遇到这个问题。

如果您可以使用可信证书访问服务器,则更好的解决scheme是正确configurationSSL,因为Android对iOS和桌面浏览器的SSLvalidation更受限制

这个解决scheme不需要你的Android应用程序的任何变化,所以它更干净。

下面是一个Apacheconfiguration示例(将其添加到您的VirtualHost定义,例如/ etc / apache2 / sites-enabled)

 SSLEngine on SSLCertificateFile YOUR_CERT_PATH SSLCACertificateFile CA_ROOT_CERT_PATH SSLCertificateKeyFile KEY_PATH 

我有同样的错误,当我添加CA根证书,错误消失了,Android没有抱怨了。 为这些文件提供正确的path,重新启动Apache并再次testing。

CA根证书的文件可以包含根证书和中间证书

您可以使用此站点testingSSLconfiguration,并确保在“ 证书path”下的结果中,服务器正在发送所有必需的证书。

当search这个exception时,你所得到的是实现“允许所有证书”的build议。

SSLPeerUnverifiedException的javadoc指出:

当对方无法识别自己(例如,没有证书,正在使用的特定密码套件不支持身份validation,或者在SSL握手期间没有build立对等身份validation时),将抛出此exception。

所以错误可能是连接是如此片状/不稳定,请求花费了大量的时间。 在我们的移动应用程序中,我们有时会经历与SSLPeerUnverifiedException结合的很多连接/套接字超时。 有些请求可以通过,但是花费60s以上 – 在这种情况下,networking连接就会超出所有方式。

简单地用“允许所有证书”暴力强制这种做法在这种情况下是不可取的,而是实施适当的重试策略。

允许Android的安全提供程序在启动应用程序时进行更新。

5.0+之前的默认Provider不禁用SSLv3。 如果您有权访问Google Play服务,则从您的应用修补Android的安全提供程序相对比较简单。

  private void updateAndroidSecurityProvider(Activity callingActivity) { try { ProviderInstaller.installIfNeeded(this); } catch (GooglePlayServicesRepairableException e) { // Thrown when Google Play Services is not installed, up-to-date, or enabled // Show dialog to allow users to install, update, or otherwise enable Google Play services. GooglePlayServicesUtil.getErrorDialog(e.getConnectionStatusCode(), callingActivity, 0); } catch (GooglePlayServicesNotAvailableException e) { Log.e("SecurityException", "Google Play Services not available."); } } 

来源: 使用ProviderInstaller提供程序修补安全提供程序

我最初使用HttpsURLConnection但它不一致工作,所以我决定去与HttpClient 。 它现在有效。