您好我正在使用Android应用程序,我需要调用Web服务,我正在使用https
协议。我可以调用简单的基于http
协议的Web服务,但没有找到任何正确的解决方案来调用https
。我找到了很多像[{3}}这样的stackoverflow线程,但它们都绕过了SSL而不是https
。我不想绕过SSL。
我这样做但是没有用。
HttpClient httpclient = new DefaultHttpClient();
// Prepare a request object
HttpGet httpget = new HttpGet(url);
// Execute the request
HttpResponse response;
try {
response = httpclient.execute(httpget);
// Examine the response status
Log.i("Praeda",response.getStatusLine().toString());
// Get hold of the response entity
HttpEntity entity = response.getEntity();
// If the response does not enclose an entity, there is no need
// to worry about connection release
if (entity != null) {
// A Simple JSON Response Read
InputStream instream = entity.getContent();
String result= convertStreamToString(instream);
// now you have the string representation of the HTML request
instream.close();
}
} catch (Exception e) {}
请帮我这样做。提前谢谢。
答案 0 :(得分:8)
这是完整的解决方案。我已经为我的申请写了这个。
/**
* This Activity is being used to show an alert about certificate exception
* while communicating to server. User can take action on the alert and
* {@link X509Certificate} will be added to trust zone if user proceed.
*/
public class SSLCertificateErrorDialogActivity extends Activity {
private static final String TAG = SSLCertificateErrorDialogActivity.class
.getSimpleName();
/** Key to send certificate via Intent between activities */
private static final String CERTIFICATE_INTENT_EXTRA = "ssl_certificate";
/** Key to send failing url via Intent between activities */
private static final String FAILING_URL_INTENT_EXTRA = "failing_url";
/** Request code for install certificate */
private static final int INSTALL_CERTIFICATE = 100;
private AlertDialog mCertificateDialog;
/**
* Certificate which needs to added to trust zone.
*/
private X509Certificate mX509Certificate;
/**
* Url which is being failed for the SSL handshake
*/
private String mFailingUrl;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// This is UI less Activity. Layout should not be set.
// Read certificate intent and install
handleIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
handleIntent(intent);
}
private void handleIntent(Intent intent) {
if (intent == null) {
Log.d(TAG, "Can not show dialog, intent is null");
finish();
return;
}
this.mX509Certificate = (X509Certificate) intent
.getSerializableExtra(CERTIFICATE_INTENT_EXTRA);
this.mFailingUrl = (String) intent.getStringExtra(FAILING_URL_INTENT_EXTRA);
if ((this.mX509Certificate == null) || (this.mFailingUrl == null)) {
Log.d(TAG,
"Can not show dialog, certificate or failingurl is null");
finish();
return;
}
// Inform user for certificate error
if ((mCertificateDialog == null)
|| (mCertificateDialog.isShowing() == false)) {
// Show dialog only when if it it not showing.
// Certificate will be updated, and will be read
// from dialog when click on ok. So no need to
// dismiss current dialog.
showSSLCertificateAcceptDialog();
}
}
@Override
public void onBackPressed() {
// Prevent back press
}
@Override
protected void onDestroy() {
if ((mCertificateDialog != null)
&& (mCertificateDialog.isShowing() == true)) {
mCertificateDialog.dismiss();
}
super.onDestroy();
}
/**
* Shows an alert dialog about SSL certificate issue. If user proceed,
* certificate will be added to trust zone, and this dialog will not be
* shown for same certificate.
*/
private void showSSLCertificateAcceptDialog() {
AlertDialog.Builder builder = new AlertDialog.Builder(
SSLCertificateErrorDialogActivity.this);
builder.setIcon(R.drawable.abouthp_icon);
builder.setTitle(R.string.untrusted_cert_dialog_title);
builder.setMessage(msg);
builder.setPositiveButton(R.string.untrusted_cert_dialog_action_ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
installCertificate();
}
});
builder.setNegativeButton(R.string.untrusted_cert_dialog_action_cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
// TODO Retry the failing url
finish();
}
});
mCertificateDialog = builder.create();
mCertificateDialog.setCancelable(false);
mCertificateDialog.show();
}
/**
* Install {@link X509Certificate} to trust zone. First this method will try
* to add certificate from background and on fail it will show a dialog to
* add certificate. This method must be called from an Activity, as it need
* an activity instance.
*/
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void installCertificate() {
X509Certificate certificate = SSLCertificateErrorDialogActivity.this.mX509Certificate;
if (certificate != null) {
byte[] encodedCert = null;
try {
encodedCert = certificate.getEncoded();
} catch (CertificateEncodingException e) {
e.printStackTrace();
}
if (encodedCert != null) {
installUsingIntent(encodedCert, INSTALL_CERTIFICATE);
}
} else {
// TODO Retry the failing url
finish();
}
}
/**
* Install certificate to trust zone using intent. User action will be
* required while installing.
*
* @param encodedCert
* of {@link X509Certificate}
* @param requestCode
*/
@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
private void installUsingIntent(byte[] encodedCert, int requestCode) {
Intent intent = KeyChain.createInstallIntent();
// Default Alias name. User can change it.
intent.putExtra(KeyChain.EXTRA_NAME, "MY Certificate");
intent.putExtra(KeyChain.EXTRA_CERTIFICATE, encodedCert);
startActivityForResult(intent, requestCode);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case INSTALL_CERTIFICATE:
// No matter if action was success or not, retry to connect with
// failed url and finish this activity.
// You can retry the failiing url
finish();
break;
default:
break;
}
}
/**
* Show {@link SSLCertificateErrorDialogActivity} to inform user that, while
* communicating to server there is untrusted certificate exception. User
* can take action, certificate will be added to trust zone if user proceed.
*
* @param context
* @param certificate
* {@link X509Certificate} to be added to trust zone.
* @param failingUrl
* is an url for SSL certificate error occurred, purpose of this
* url is to retry the same url after user action either
* cancelled or proceed.
*/
public static void show(Context context, X509Certificate certificate,
String failingUrl) {
Context appContext = context.getApplicationContext();
Intent intent = new Intent(appContext,
SSLCertificateErrorDialogActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
intent.putExtra(CERTIFICATE_INTENT_EXTRA, certificate);
intent.putExtra(FAILING_URL_INTENT_EXTRA, failingUrl);
appContext.startActivity(intent);
}
}
这是实用程序类,它可以帮助您处理SSL证书错误并安装到设备
import java.io.IOException;
import java.net.Socket;
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 java.util.Enumeration;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.AllowAllHostnameVerifier;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
import android.content.Context;
import android.util.Log;
/**
* This class will perform all network related calls like post, get and put.
*/
public class NetworkUtility {
protected static final String TAG = NetworkUtility.class.getSimpleName();
/**
* Connection timeout. 15 seconds
*/
private static final int HTTP_CONNECTION_TIMEOUT = 150000;
/**
* Returns Default HTTP client with socket factories initialised.
*
* @param context
* @param targetUrl
* to do request
* @return Default HTTP Client
*/
private static HttpClient getDefaultHttpClient(Context context,
String targetUrl) {
HttpParams params = new BasicHttpParams();
HttpConnectionParams.setConnectionTimeout(params,
HTTP_CONNECTION_TIMEOUT);
HttpConnectionParams.setSoTimeout(params, HTTP_CONNECTION_TIMEOUT);
try {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
registry.register(new Scheme("https", new MySSLSocketFactory(
context.getApplicationContext(), targetUrl), 443));
ClientConnectionManager ccm = new ThreadSafeClientConnManager(
params, registry);
return new DefaultHttpClient(ccm, params);
} catch (Exception e) {
e.printStackTrace();
return new DefaultHttpClient(params);
}
}
/**
* TrustManager to accept all certificates. It does not do any certificates
* validation.
*
* TODO: Once we have actual certificates this implementation should be
* changed accordingly.
*/
private static class MyTrustManager implements X509TrustManager {
private X509TrustManager mOriginalX509TrustManager;
private Context mContext;
private String mTargetUrl;
/**
* @param context
* - application context.
* @param targetUrl
* - to do request.
*/
public MyTrustManager(Context context, String targetUrl) {
try {
this.mContext = context;
this.mTargetUrl = targetUrl;
TrustManagerFactory originalTrustManagerFactory = TrustManagerFactory
.getInstance("X509");
originalTrustManagerFactory.init((KeyStore) null);
TrustManager[] originalTrustManagers = originalTrustManagerFactory
.getTrustManagers();
this.mOriginalX509TrustManager = (X509TrustManager) originalTrustManagers[0];
} catch (Exception e) {
e.printStackTrace();
}
}
public void checkClientTrusted(X509Certificate[] cert, String authType)
throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] cert, String authType)
throws CertificateException {
try {
// Verify if the certificate has been trusted.
// This validation will pass if certificate has
// been added by user or system.
mOriginalX509TrustManager.checkServerTrusted(cert, authType);
} catch (CertificateException originalException) {
// Certificate has not present into trust zone.
// Find first certificate from the array of certificates which
// needs to install.
X509Certificate certificate = getCertificateToInstall(cert);
Log.d(TAG, "Showing dialog for certificate exception...");
// Show dialog where user can install this certificate
SSLCertificateErrorDialogActivity.show(this.mContext,
certificate, this.mTargetUrl);
throw originalException;
}
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
}
/**
* Get certificate to be installed from the given list of certificates. It
* iterates all certificates from CA and if a certificate, from the given
* array is not present into CA, this method returns that certificate.
*
* @param certificates
* @return {@link X509Certificate} to install.
*/
private static X509Certificate getCertificateToInstall(
X509Certificate[] certificates) {
X509Certificate result = null;
try {
KeyStore ks = KeyStore.getInstance("AndroidCAStore");
if (ks != null) {
ks.load(null, null);
boolean certFound = false;
for (X509Certificate certificate : certificates) {
Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
String alias = (String) aliases.nextElement();
X509Certificate cert = (X509Certificate) ks
.getCertificate(alias);
if (certificate.equals(cert) == true) {
certFound = true;
break;
}
}
if (certFound == false) {
Log.d(TAG, "Not found certificate");
// Need to install this certificate
result = certificate;
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
private static class MySSLSocketFactory extends SSLSocketFactory {
private javax.net.ssl.SSLSocketFactory mFactory;
public MySSLSocketFactory(Context context, String targetUrl)
throws KeyManagementException, NoSuchAlgorithmException,
KeyStoreException, UnrecoverableKeyException {
super((KeyStore) null);
try {
SSLContext sslcontext = SSLContext.getInstance("TLS");
sslcontext.init(null, new TrustManager[] { new MyTrustManager(
context, targetUrl) }, null);
mFactory = sslcontext.getSocketFactory();
setHostnameVerifier(new AllowAllHostnameVerifier());
} catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public Socket createSocket() throws IOException {
return mFactory.createSocket();
}
@Override
public Socket createSocket(Socket socket, String s, int i, boolean flag)
throws IOException {
return mFactory.createSocket(socket, s, i, flag);
}
}
}
使用非常简单,如下所示
HttpGet httpGet = new HttpGet(url);
HttpClient httpClient = getDefaultHttpClient(context, url);
HttpResponse response = httpClient.execute(httpGet);
答案 1 :(得分:0)
试试这个: -
SSLContext sslContext = SSLContext.getInstance("SSL");
// set up a TrustManager that trusts everything
sslContext.init(null, new TrustManager[] { new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
System.out.println("getAcceptedIssuers =============");
return null;
}
public void checkClientTrusted(X509Certificate[] certs,
String authType) {
System.out.println("checkClientTrusted =============");
}
public void checkServerTrusted(X509Certificate[] certs,
String authType) {
System.out.println("checkServerTrusted =============");
}
} }, new SecureRandom());
SSLSocketFactory sf = new SSLSocketFactory(sslContext);
Scheme httpsScheme = new Scheme("https", 443, sf);
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(httpsScheme);
// apache HttpClient version >4.2 should use BasicClientConnectionManager
ClientConnectionManager cm = new SingleClientConnManager(schemeRegistry);
HttpClient httpClient = new DefaultHttpClient(cm);