Я пытаюсь сделать простой HttpGet, чтобы прочитать веб-страницу. У меня это работает на iOS и работает на Android через HTTP, а не https.
URL-адрес является внутренним IP-сети и пользовательский порт, поэтому я могу читать с HTTP, как это, используя путь 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, я получаю ошибка нет взаимного сертификата. Поэтому я попытался с помощью этого кода:
С помощью HttpClient HttpClient, который = новый 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();
}
}
но это дает мне соединение закрыто ошибка сверстников
.
Что я делаю не так? Я могу спокойно игнорировать сертификат, как это'с внутренней сети с самозаверенный сертификат, однако я не имеем никакого контроля над Верт и пользователи моего приложения могут иметь различные сертификаты, так что я действительно нужно, чтобы автоматически принимать или обходить его.
Спасибо
Редактировать ------------------------------
После попытки мое имя-это ответ ниже: Я'вэ создал класс CustomX509TrustManager, как полагают, затем создать пользовательский класс 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;
Вошедший в путь в формате https://ipaddress:8080/Page.html
Но я получаю соединение закрыто ошибка коллегиального
:
05-24 08:20:32.500: е/ConnectionHelper(1129): исключение IOException 05-24 08:20:32.550: е/ConnectionHelper(1129): исключение загрузка содержимого 05-24 08:20:32.550: е/ConnectionHelper(1129): класс javax.чистая.протокол SSL.SSLException: соединение закрыто коллегиального 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".гармонии.сети xnet.поставщика.по jsse.NativeCrypto.SSL_do_handshake(Родной способ) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".гармонии.сети xnet.поставщика.по jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.Ява:410) 05-24 08:20:32.550: е/ConnectionHelper(1129): в org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLInputStream.
(OpenSSLSocketImpl.java:643) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".гармонии.сети xnet.поставщика.по jsse.OpenSSLSocketImpl.getInputStream(OpenSSLSocketImpl.Ява:614) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".протоколу HTTP.осущ.Ио.SocketInputBuffer.<инициализации и GT;(SocketInputBuffer.Ява:70) 05-24 08:20:32.550: е/ConnectionHelper(1129): в org.apache.http.impl.SocketHttpClientConnection.createSessionInputBuffer(SocketHttpClientConnection.java:83) 05-24 08:20:32.550: е/ConnectionHelper(1129): в org.apache.http.impl.conn.DefaultClientConnection.createSessionInputBuffer(DefaultClientConnection.java:170) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".протоколу HTTP.осущ.SocketHttpClientConnection.привязать(SocketHttpClientConnection.Ява:106) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".протоколу HTTP.осущ.соед.DefaultClientConnection.openCompleted(DefaultClientConnection.Ява:129) 05-24 08:20:32.550: е/ConnectionHelper(1129): в org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:172) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".протоколу HTTP.осущ.соед.AbstractPoolEntry.открыть(AbstractPoolEntry.Ява:164) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".протоколу HTTP.осущ.соед.AbstractPooledConnAdapter.открыть(AbstractPooledConnAdapter.Ява:119) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".протоколу HTTP.осущ.клиента.DefaultRequestDirector.выполнить(DefaultRequestDirector.Ява:360) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".протоколу HTTP.осущ.клиента.AbstractHttpClient.выполнить(AbstractHttpClient.Ява:555) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".протоколу HTTP.осущ.клиента.AbstractHttpClient.выполнить(AbstractHttpClient.Ява:487) 05-24 08:20:32.550: е/ConnectionHelper(1129): в орг."Апач".протоколу HTTP.осущ.клиента.AbstractHttpClient.выполнить(AbstractHttpClient.Ява:465) 05-24 08:20:32.550: е/ConnectionHelper(1129): в com.d_apps.my_app.connection_helpers.ConnectionHelper$httpGETTask.doInBackground(ConnectionHelper.java:114)
Следующие источник должен исправить вашу проблему.
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. (e.g. 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;
}
}
Если вы используете "и не доверять"(разработчик) сертификат, то ниже есть решение. Нам нужно доверять все сертификаты, и ниже это способ сделать это. Для доверенных сертификатов он работает без добавления ниже функциональные возможности, то просто нужно менять HTTP на HTTPS и будет работать.
Вот решение для не доверенный сертификат.
В сторону с помощью HttpClient, вы должны создать пользовательский класс с орг."Апач".протоколу HTTP.соед.протокол SSL.Sslsocketfactory не, не один орг."Апач".протоколу HTTP.соед.протокол 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();
}
}
и использовать этот класс, создавая экземпляр класса HttpClient.
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();
}
}
Если у вас есть доступ к серверу с доверенным сертификатом гораздо лучше solutionis правильно настроить протокол SSL, потому что Android является более ограниченным, что iOS и браузер по протоколу SSL проверки
Данное решение не требует внесения изменений в ваше Android-приложение, поэтому он является более чистым.
Вот пример конфигурации SSL для Apache (добавить его в свой хост определение, например /etc/apache2 не/сайты-включено)
SSLEngine on
SSLCertificateFile YOUR_CERT_PATH
SSLCACertificateFile CA_ROOT_CERT_PATH
SSLCertificateKeyFile KEY_PATH
У меня была такая же ошибка и когда я добавил корневой сертификат центра сертификации, ошибка ушла и Android не жалуются. Указывать правильные пути для этих файлов, перезапустите Apache и проверить.
Файл для корневого центра сертификации сертификат может содержать корневого и промежуточного сертификата
Вы можете проверить вашу конфигурацию SSL с этом сайте и убедитесь в том, что в результате под пути сертификации что сервер отправляет все необходимые сертификаты.
При поиске на это исключение, все, что вы получаете рекомендации по выполнению и"разрешить все сертификаты и".
Javadoc для государства SSLPeerUnverifiedException:
когда узел не был в состоянии идентифицировать себя (например, нет сертификата, в частности шифра используется Suite не поддерживает проверку подлинности или не подлинности одноранговых был создан во время квитирования SSL) это исключение.
Поэтому ошибка может быть в том, что связь настолько шелушащейся/нестабильная и просит принять нелепое количество времени. В нашем мобильном приложении мы иногда испытывают много's для подключения/цоколь-время ожидания в сочетании с этими SSLPeerUnverifiedException. Некоторые запросы дозвониться, но брать 60-х годов+ - подключение к сети просто хреново за все средства в этих случаях.
Просто перебирая это в "разрешить все сертификаты" не рекомендуется в таких случаях - скорее реализовать правильную стратегию повтора.
Позволить Android's-провайдером безопасности обновить при запуске вашего приложения.
Поставщик по умолчанию до 5.0+ не отключить SSLv3. Если у вас есть доступ к сервисам Google Play это относительно просто патч для Android's-провайдером безопасности от вашего приложения.
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`. Она работает сейчас.