最近在Https上发布了有关HttpClient的问题( 在此处找到 )。 我取得了一些进展,但遇到了新问题。 与我的最后一个问题一样,我似乎找不到任何适合我的示例。 基本上,我希望我的客户端接受任何证书(因为我只指向一台服务器),但是我不断收到javax.net.ssl.SSLException: Not trusted server certificate exception.

这就是我所拥有的:

public void connect() throws A_WHOLE_BUNCH_OF_EXCEPTIONS {HttpPost post = new HttpPost(new URI(PROD_URL));post.setEntity(new StringEntity(BODY));KeyStore trusted = KeyStore.getInstance("BKS");trusted.load(null, "".toCharArray());SSLSocketFactory sslf = new SSLSocketFactory(trusted);sslf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);SchemeRegistry schemeRegistry = new SchemeRegistry();schemeRegistry.register(new Scheme ("https", sslf, 443));SingleClientConnManager cm = new SingleClientConnManager(post.getParams(),schemeRegistry);HttpClient client = new DefaultHttpClient(cm, post.getParams());HttpResponse result = client.execute(post);}

这是我得到的错误:

    W/System.err(  901): javax.net.ssl.SSLException: Not trusted server certificate W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:360) W/System.err(  901):    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:92) W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:321) W/System.err(  901):    at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:129) W/System.err(  901):    at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164) W/System.err(  901):    at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119) W/System.err(  901):    at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:348) W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555) W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487) W/System.err(  901):    at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465) W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:129) W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.access$0(MainActivity.java:77) W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity$2.run(MainActivity.java:49) W/System.err(  901): Caused by: java.security.cert.CertificateException: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.checkServerTrusted(TrustManagerImpl.java:157) W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:355) W/System.err(  901):    ... 12 more W/System.err(  901): Caused by: java.security.InvalidAlgorithmParameterException: the trust anchors set is empty W/System.err(  901):    at java.security.cert.PKIXParameters.checkTrustAnchors(PKIXParameters.java:645) W/System.err(  901):    at java.security.cert.PKIXParameters.<init>(PKIXParameters.java:89) W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerImpl.<init>(TrustManagerImpl.java:89) W/System.err(  901):    at org.apache.harmony.xnet.provider.jsse.TrustManagerFactoryImpl.engineGetTrustManagers(TrustManagerFactoryImpl.java:134) W/System.err(  901):    at javax.net.ssl.TrustManagerFactory.getTrustManagers(TrustManagerFactory.java:226)W/System.err(  901):     at org.apache.http.conn.ssl.SSLSocketFactory.createTrustManagers(SSLSocketFactory.java:263) W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:190) W/System.err(  901):    at org.apache.http.conn.ssl.SSLSocketFactory.<init>(SSLSocketFactory.java:216) W/System.err(  901):    at me.harrisonlee.test.ssl.MainActivity.connect(MainActivity.java:107) W/System.err(  901):    ... 2 more

#1楼

任何仍在使用Android 2.1上的StartCom SSL证书苦苦挣扎的机构,请访问https://www.startssl.com/certs/并下载ca.pem,现在位于@emmby replace提供的答案中

`export CLASSPATH=bcprov-jdk16-145.jarCERTSTORE=res/raw/mystore.bksif [ -a $CERTSTORE ]; thenrm $CERTSTORE || exit 1fikeytool \-import \-v \-trustcacerts \-alias 0 \-file <(openssl x509 -in mycert.pem) \-keystore $CERTSTORE \-storetype BKS \-provider org.bouncycastle.jce.provider.BouncyCastleProvider \-providerpath /usr/share/java/bcprov.jar \-storepass some-password`

 `export CLASSPATH=bcprov-jdk16-145.jarCERTSTORE=res/raw/mystore.bksif [ -a $CERTSTORE ]; thenrm $CERTSTORE || exit 1fikeytool \-import \-v \-trustcacerts \-alias 0 \-file <(openssl x509 -in ca.pem) \-keystore $CERTSTORE \-storetype BKS \-provider org.bouncycastle.jce.provider.BouncyCastleProvider \-providerpath /usr/share/java/bcprov.jar \-storepass some-password`

应该开箱即用。 即使经过@emmby的完美回答,我也努力奋斗了整整一天 。希望这对某人有帮助...


#2楼

HttpComponents的API已更改。 它与下面的代码一起使用。

public static HttpClient getTestHttpClient() {try {SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){@Overridepublic boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {return true;}}, new AllowAllHostnameVerifier());SchemeRegistry registry = new SchemeRegistry();registry.register(new Scheme("https",8444, sf));ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);return new DefaultHttpClient(ccm);} catch (Exception e) {e.printStackTrace();return new DefaultHttpClient();}
}

#3楼

对于那些希望允许所有证书在OAuth上运行(出于测试目的)的人,请执行以下步骤:

1)在此处下载Android OAuth API的源代码: https : //github.com/kaeppler/signpost

2)查找文件“ CommonsHttpOAuthProvider”类

3)进行如下更改:

public class CommonsHttpOAuthProvider extends AbstractOAuthProvider {private static final long serialVersionUID = 1L;private transient HttpClient httpClient;public CommonsHttpOAuthProvider(String requestTokenEndpointUrl, String accessTokenEndpointUrl,String authorizationWebsiteUrl) {super(requestTokenEndpointUrl, accessTokenEndpointUrl, authorizationWebsiteUrl);//this.httpClient = new DefaultHttpClient();//Version implemented and that throws the famous "javax.net.ssl.SSLException: Not trusted server certificate" if the certificate is not signed with a CAthis.httpClient = MySSLSocketFactory.getNewHttpClient();//This will work with all certificates (for testing purposes only)
}

上面的“ MySSLSocketFactory”基于公认的答案。 为了使它更加容易,这里有完整的类:

package com.netcomps.oauth_example;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.HttpVersion;
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.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.HttpParams;
import org.apache.http.params.HttpProtocolParams;
import org.apache.http.protocol.HTTP;//http://stackoverflow.com/questions/2642777/trusting-all-certificates-using-httpclient-over-https
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() {@Overridepublic void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}@Overridepublic 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();
}public static 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();}
}

}

希望这对某人有帮助。


#4楼

信任所有证书对我而言并不是真正的选择,因此我执行以下操作以使HttpsURLConnection信任新证书(另请参见http://nelenkov.blogspot.jp/2011/12/using-custom-certificate-trust-store- on.html )。

  1. 获得证书; 通过在Firefox中导出证书(单击小锁图标,获取证书详细信息,单击导出),然后使用portecle导出信任库(BKS),可以完成此任务。

  2. 使用以下代码从/res/raw/geotrust_cert.bks加载信任库:

      final KeyStore trustStore = KeyStore.getInstance("BKS"); final InputStream in = context.getResources().openRawResource( R.raw.geotrust_cert); trustStore.load(in, null); final TrustManagerFactory tmf = TrustManagerFactory .getInstance(TrustManagerFactory.getDefaultAlgorithm()); tmf.init(trustStore); final SSLContext sslCtx = SSLContext.getInstance("TLS"); sslCtx.init(null, tmf.getTrustManagers(), new java.security.SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory(sslCtx .getSocketFactory()); 

#5楼

使用所有https

httpClient = new DefaultHttpClient();SSLContext ctx = SSLContext.getInstance("TLS");
X509TrustManager tm = new X509TrustManager() {public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }public X509Certificate[] getAcceptedIssuers() {return null;}
};ctx.init(null, new TrustManager[]{tm}, null);
SSLSocketFactory ssf = new SSLSocketFactory(ctx, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);httpClient.getConnectionManager().getSchemeRegistry().register(new Scheme("https", 443, ssf));

#6楼

只需使用-

public DefaultHttpClient wrapClient(HttpClient base) {try {SSLContext ctx = SSLContext.getInstance("TLS");X509TrustManager tm = new X509TrustManager() {public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }public X509Certificate[] getAcceptedIssuers() {return null;}};ctx.init(null, new TrustManager[]{tm}, null);SSLSocketFactory ssf = new SSLSocketFactory(ctx);ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);ClientConnectionManager ccm = base.getConnectionManager();SchemeRegistry sr = ccm.getSchemeRegistry();sr.register(new Scheme("https", ssf, 443));return new DefaultHttpClient(ccm, base.getParams());
} catch (Exception ex) {return null;
}
}

#7楼

上面有很多答案,但是我无法(在有限的时间内)使它们中的任何一个正常工作,因此对于处于相同情况的其他任何人,您都可以尝试下面的代码,这些代码非常适合我的Java测试目的:

    public static HttpClient wrapClient(HttpClient base) {try {SSLContext ctx = SSLContext.getInstance("TLS");X509TrustManager tm = new X509TrustManager() {public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException { }public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException { }public X509Certificate[] getAcceptedIssuers() {return null;}};ctx.init(null, new TrustManager[]{tm}, null);SSLSocketFactory ssf = new SSLSocketFactory(ctx);ssf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);ClientConnectionManager ccm = base.getConnectionManager();SchemeRegistry sr = ccm.getSchemeRegistry();sr.register(new Scheme("https", ssf, 443));return new DefaultHttpClient(ccm, base.getParams());} catch (Exception ex) {return null;}
}

然后像这样打电话:

DefaultHttpClient baseClient = new DefaultHttpClient();
HttpClient httpClient = wrapClient(baseClient );

参考: http : //tech.chitgoks.com/2011/04/24/how-to-avoid-javax-net-ssl-sslpeerunverifiedexception-peer-not-authenticated-problem-using-apache-httpclient/


#8楼

上面https://stackoverflow.com/a/6378872/1553004中的代码是正确的,除了它还必须调用主机名验证程序:

    @Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {SSLSocket sslSocket = (SSLSocket)sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);getHostnameVerifier().verify(host, sslSocket);return sslSocket;
}

我明确注册了stackoverflow以添加此修复程序。 注意我的警告!


#9楼

自API 8开始,您可以通过以下方式禁用HttpURLConnection SSL检查以进行测试:

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();if (conn instanceof HttpsURLConnection) {HttpsURLConnection httpsConn = (HttpsURLConnection) conn;httpsConn.setSSLSocketFactory(SSLCertificateSocketFactory.getInsecure(0, null));httpsConn.setHostnameVerifier(new AllowAllHostnameVerifier());}

#10楼

我正在为使用httpclient-4.5的用户添加响应,并且可能也适用于4.4。

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.HttpResponseException;
import org.apache.http.client.fluent.ContentResponseHandler;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;public class HttpClientUtils{public static HttpClient getHttpClientWithoutSslValidation_UsingHttpClient_4_5_2() {try {SSLContextBuilder builder = new SSLContextBuilder();builder.loadTrustMaterial(null, new TrustStrategy() {@Overridepublic boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {return true;}});SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(builder.build(), new NoopHostnameVerifier());CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(sslsf).build(); return httpclient;} catch (Exception e) {throw new RuntimeException(e);}
}
}

#11楼

我使用了它,它在所有OS上都适用。

/*** Disables the SSL certificate checking for new instances of {@link HttpsURLConnection} This has been created to* aid testing on a local box, not for use on production.*/private static void disableSSLCertificateChecking() {TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {public X509Certificate[] getAcceptedIssuers() {return null;}@Overridepublic void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {// Not implemented}@Overridepublic void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {// Not implemented}} };try {SSLContext sc = SSLContext.getInstance("TLS");sc.init(null, trustAllCerts, new java.security.SecureRandom());HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());} catch (KeyManagementException e) {e.printStackTrace();} catch (NoSuchAlgorithmException e) {e.printStackTrace();}
}

#12楼

只需在VM参数上添加-Dtrust_all_cert=true即可。 此参数告诉Java忽略证书检查。


#13楼

注意:不要在您不完全信任的网络上使用的生产代码中实现此功能。 尤其是通过公共互联网进行的任何操作。

您的问题就是我想知道的。 经过一些搜索,结论如下。

以HttpClient方式,您应该从org.apache.http.conn.ssl.SSLSocketFactory创建一个自定义类,而不是一个org.apache.http.conn.ssl.SSLSocketFactory本身。 在这篇文章中可以找到一些线索。 自定义SSL处理已在Android 2.2 FroYo上停止工作 。

一个例子就像...

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);}@Overridepublic Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);}@Overridepublic Socket createSocket() throws IOException {return sslContext.getSocketFactory().createSocket();}
}

并在创建HttpClient实例时使用此类。

public HttpClient getNewHttpClient() {try {KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());trustStore.load(null, null);MySSLSocketFactory 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();}
}

顺便说一句,下面的链接适用于正在寻找HttpURLConnection解决方案的人。 Https连接Android

我已经在froyo上测试了上述两种解决方案,在我的案例中,它们都像魅力一样起作用。 最后,使用HttpURLConnection可能会遇到重定向问题,但这超出了主题。

注意:在决定信任所有证书之前,您可能应该充分了解该站点,并且不会对最终用户造成危害。

确实,应该谨慎考虑您所冒的风险,包括以下我深为赞赏的评论中提到的黑客模拟站点的影响。 在某些情况下,尽管可能很难处理所有证书,但您最好知道信任所有证书的隐式缺点。


#14楼

使用这个课程

public class WCFs
{//  https://192.168.30.8/myservice.svc?wsdl
private static final String NAMESPACE = "http://tempuri.org/";
private static final String URL = "192.168.30.8";
private static final String SERVICE = "/myservice.svc?wsdl";
private static String SOAP_ACTION = "http://tempuri.org/iWCFserviceMe/";public static Thread myMethod(Runnable rp)
{String METHOD_NAME = "myMethod";SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);request.addProperty("Message", "Https WCF Running...");return _call(rp,METHOD_NAME, request);
}protected static HandlerThread _call(final RunProcess rp,final String METHOD_NAME, SoapObject soapReq)
{final SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);int TimeOut = 5*1000;envelope.dotNet = true;envelope.bodyOut = soapReq;envelope.setOutputSoapObject(soapReq);final HttpsTransportSE httpTransport_net = new HttpsTransportSE(URL, 443, SERVICE, TimeOut);try{HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() // use this section if crt file is handmake{@Overridepublic boolean verify(String hostname, SSLSession session){return true;}});KeyStore k = getFromRaw(R.raw.key, "PKCS12", "password");((HttpsServiceConnectionSE) httpTransport_net.getServiceConnection()).setSSLSocketFactory(getSSLSocketFactory(k, "SSL"));}catch(Exception e){}HandlerThread thread = new HandlerThread("wcfTd"+ Generator.getRandomNumber()){@Overridepublic void run(){Handler h = new Handler(Looper.getMainLooper());Object response = null;for(int i=0; i<4; i++){response = send(envelope, httpTransport_net , METHOD_NAME, null);try{if(Thread.currentThread().isInterrupted()) return;}catch(Exception e){}if(response != null)break;ThreadHelper.threadSleep(250);}if(response != null){if(rp != null){rp.setArguments(response.toString());h.post(rp);}}else{if(Thread.currentThread().isInterrupted())return;if(rp != null){rp.setExceptionState(true);h.post(rp);}}ThreadHelper.stopThread(this);}};thread.start();return thread;
}private static Object send(SoapSerializationEnvelope envelope, HttpTransportSE androidHttpTransport, String METHOD_NAME, List<HeaderProperty> headerList)
{try{if(headerList != null)androidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope, headerList);elseandroidHttpTransport.call(SOAP_ACTION + METHOD_NAME, envelope);Object res = envelope.getResponse();if(res instanceof SoapPrimitive)return (SoapPrimitive) envelope.getResponse();else if(res instanceof SoapObject)return ((SoapObject) envelope.getResponse());}catch(Exception e){}return null;
}public static KeyStore getFromRaw(@RawRes int id, String algorithm, String filePassword)
{try{InputStream inputStream = ResourceMaster.openRaw(id);KeyStore keystore = KeyStore.getInstance(algorithm);keystore.load(inputStream, filePassword.toCharArray());inputStream.close();return keystore;}catch(Exception e){}return null;
}public static SSLSocketFactory getSSLSocketFactory(KeyStore trustKey, String SSLAlgorithm)
{try{TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());tmf.init(trustKey);SSLContext context = SSLContext.getInstance(SSLAlgorithm);//"SSL" "TLS"context.init(null, tmf.getTrustManagers(), null);return context.getSocketFactory();}catch(Exception e){}return null;
}

}


#15楼

将此代码添加到HttpsURLConnection之前,即可完成。 我知道了。

private void trustEveryone() { try { HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier(){ public boolean verify(String hostname, SSLSession session) { return true; }}); SSLContext context = SSLContext.getInstance("TLS"); context.init(null, new X509TrustManager[]{new X509TrustManager(){ public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {} public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }}}, new SecureRandom()); HttpsURLConnection.setDefaultSSLSocketFactory( context.getSocketFactory()); } catch (Exception e) { // should never happen e.printStackTrace(); }
}

我希望这可以帮助你。


#16楼

这是一个坏主意。 完全信任任何证书比完全不使用SSL略好。 当您说“我希望我的客户接受任何证书(因为我只指向一台服务器)”时,您假设这意味着以某种方式指向“一台服务器”是安全的,但它不在公共网络上。

通过信任任何证书,您完全可以接受中间人攻击。 任何人都可以通过与您以及与终端服务器建立单独的SSL连接来代理您的连接。 然后,MITM可以访问您的整个请求和响应。 除非您一开始并不真正需要SSL(您的消息没有任何敏感内容,并且不进行身份验证),否则您不应盲目地信任所有证书。

您应该考虑使用keytool将公共证书添加到jks,并使用它来构建套接字工厂,例如:

    KeyStore ks = KeyStore.getInstance("JKS");// get user password and file input streamchar[] password = ("mykspassword")).toCharArray();ClassLoader cl = this.getClass().getClassLoader();InputStream stream = cl.getResourceAsStream("myjks.jks");ks.load(stream, password);stream.close();SSLContext sc = SSLContext.getInstance("TLS");KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");kmf.init(ks, password);tmf.init(ks);sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(),null);return sc.getSocketFactory();

有一个警告需要注意。 证书最终将过期,并且代码将在那时停止工作。 您可以通过查看证书轻松确定何时发生这种情况。


#17楼

在此处输入图片说明

xamarin android中的sspi失败。

我找到了解决方案; 在点击HTTPS链接之前放置此代码

const SslProtocols _Tls12 = (SslProtocols)0x00000C00;
const SecurityProtocolType Tls12 = (SecurityProtocolType)_Tls12;
ServicePointManager.SecurityProtocol = Tls12;

#18楼

基本上,您有四种可能的解决方案,可以使用httpclient在Android上修复“不可信”异常:

  1. 信任所有证书。 除非您真的知道自己在做什么,否则不要这样做。
  2. 创建一个仅信任您的证书的自定义SSLSocketFactory。 只要您确切知道将要连接到哪些服务器,此方法就可以工作,但是一旦您需要使用其他SSL证书连接到新服务器时,就需要更新应用程序。
  3. 创建一个包含Android证书的“主列表”的密钥库文件,然后添加自己的证书。 如果这些证书中的任何一个在将来失效,则您有责任在您的应​​用程序中对其进行更新。 我想不出这样做的理由。
  4. 创建一个使用内置证书KeyStore的自定义SSLSocketFactory,但在备用KeyStore上使用任何无法使用默认值进行验证的内容。

此答案使用解决方案#4,在我看来,这是最可靠的解决方案。

解决方案是使用可以接受多个KeyStore的SSLSocketFactory,从而允许您为自己的KeyStore提供自己的证书。 这使您可以加载某些Android设备上可能缺少的其他顶级证书,例如Thawte。 它还允许您加载自己的自签名证书。 它将首先使用内置的默认设备证书,然后仅在必要时才使用其他证书。

首先,您需要确定KeyStore中缺少的证书。 运行以下命令:

openssl s_client -connect www.yourserver.com:443

您将看到类似以下的输出:

Certificate chain0 s:/O=www.yourserver.com/OU=Go to https://www.thawte.com/repository/index.html/OU=Thawte SSL123 certificate/OU=Domain Validated/CN=www.yourserver.comi:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CA1 s:/C=US/O=Thawte, Inc./OU=Domain Validated SSL/CN=Thawte DV SSL CAi:/C=US/O=thawte, Inc./OU=Certification Services Division/OU=(c) 2006 thawte, Inc. - For authorized use only/CN=thawte Primary Root CA

如您所见,我们的根证书来自Thawte。 转到提供商的网站并找到相应的证书。 对于我们来说,就在这里 ,您可以看到我们需要的是版权2006。

如果您使用的是自签名证书,则不需要执行上一步,因为您已经拥有签名证书。

然后,创建包含缺少签名证书的密钥库文件。 Crazybob包含了如何在Android上执行此操作的详细信息 ,但想法是执行以下操作:

如果尚未安装,请从http://www.bouncycastle.org/latest_releases.html下载充气城堡提供程序库。 这将在下面的类路径中进行。

运行命令以从服务器提取证书并创建一个pem文件。 在这种情况下,为mycert.pem。

echo | openssl s_client -connect ${MY_SERVER}:443 2>&1 | \sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > mycert.pem

然后运行以下命令来创建密钥库。

export CLASSPATH=/path/to/bouncycastle/bcprov-jdk15on-155.jar
CERTSTORE=res/raw/mystore.bks
if [ -a $CERTSTORE ]; thenrm $CERTSTORE || exit 1
fi
keytool \-import \-v \-trustcacerts \-alias 0 \-file <(openssl x509 -in mycert.pem) \-keystore $CERTSTORE \-storetype BKS \-provider org.bouncycastle.jce.provider.BouncyCastleProvider \-providerpath /path/to/bouncycastle/bcprov-jdk15on-155.jar \-storepass some-password

您会注意到上面的脚本将结果放置在res/raw/mystore.bks 。 现在,您将拥有一个文件,可以将其加载到提供缺失证书的Android应用中。

为此,请为SSL方案注册SSLSocketFactory:

final SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
schemeRegistry.register(new Scheme("https", createAdditionalCertsSSLSocketFactory(), 443));// and then however you create your connection manager, I use ThreadSafeClientConnManager
final HttpParams params = new BasicHttpParams();
...
final ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params,schemeRegistry);

要创建SSLSocketFactory:

protected org.apache.http.conn.ssl.SSLSocketFactory createAdditionalCertsSSLSocketFactory() {try {final KeyStore ks = KeyStore.getInstance("BKS");// the bks file we generated abovefinal InputStream in = context.getResources().openRawResource( R.raw.mystore);  try {// don't forget to put the password used above in strings.xml/mystore_passwordks.load(in, context.getString( R.string.mystore_password ).toCharArray());} finally {in.close();}return new AdditionalKeyStoresSSLSocketFactory(ks);} catch( Exception e ) {throw new RuntimeException(e);}
}

最后,AdditionalKeyStoresSSLSocketFactory代码,该代码接受您的新KeyStore并检查内置KeyStore是否无法验证SSL证书:

/*** Allows you to trust certificates from additional KeyStores in addition to* the default KeyStore*/
public class AdditionalKeyStoresSSLSocketFactory extends SSLSocketFactory {protected SSLContext sslContext = SSLContext.getInstance("TLS");public AdditionalKeyStoresSSLSocketFactory(KeyStore keyStore) throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException, UnrecoverableKeyException {super(null, null, null, null, null, null);sslContext.init(null, new TrustManager[]{new AdditionalKeyStoresTrustManager(keyStore)}, null);}@Overridepublic Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException {return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);}@Overridepublic Socket createSocket() throws IOException {return sslContext.getSocketFactory().createSocket();}/*** Based on http://download.oracle.com/javase/1.5.0/docs/guide/security/jsse/JSSERefGuide.html#X509TrustManager*/public static class AdditionalKeyStoresTrustManager implements X509TrustManager {protected ArrayList<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();protected AdditionalKeyStoresTrustManager(KeyStore... additionalkeyStores) {final ArrayList<TrustManagerFactory> factories = new ArrayList<TrustManagerFactory>();try {// The default Trustmanager with default keystorefinal TrustManagerFactory original = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());original.init((KeyStore) null);factories.add(original);for( KeyStore keyStore : additionalkeyStores ) {final TrustManagerFactory additionalCerts = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());additionalCerts.init(keyStore);factories.add(additionalCerts);}} catch (Exception e) {throw new RuntimeException(e);}/** Iterate over the returned trustmanagers, and hold on* to any that are X509TrustManagers*/for (TrustManagerFactory tmf : factories)for( TrustManager tm : tmf.getTrustManagers() )if (tm instanceof X509TrustManager)x509TrustManagers.add( (X509TrustManager)tm );if( x509TrustManagers.size()==0 )throw new RuntimeException("Couldn't find any X509TrustManagers");}/** Delegate to the default trust manager.*/public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {final X509TrustManager defaultX509TrustManager = x509TrustManagers.get(0);defaultX509TrustManager.checkClientTrusted(chain, authType);}/** Loop over the trustmanagers until we find one that accepts our server*/public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {for( X509TrustManager tm : x509TrustManagers ) {try {tm.checkServerTrusted(chain,authType);return;} catch( CertificateException e ) {// ignore}}throw new CertificateException();}public X509Certificate[] getAcceptedIssuers() {final ArrayList<X509Certificate> list = new ArrayList<X509Certificate>();for( X509TrustManager tm : x509TrustManagers )list.addAll(Arrays.asList(tm.getAcceptedIssuers()));return list.toArray(new X509Certificate[list.size()]);}}}

#19楼

Daniel的回答很好,只是我不得不更改此代码...

    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);

这个代码...

    ClientConnectionManager ccm = new ThreadSafeClientConnManager(params, registry);SchemeRegistry registry = ccm.getShemeRegistry()registry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));registry.register(new Scheme("https", sf, 443));

使它工作。


#20楼

这是一个使用4.1.2 httpclient代码的简单版本。 然后可以将其修改为您认为合适的任何信任算法。

public static HttpClient getTestHttpClient() {try {SSLSocketFactory sf = new SSLSocketFactory(new TrustStrategy(){@Overridepublic boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {return true;}});SchemeRegistry registry = new SchemeRegistry();registry.register(new Scheme("https", 443, sf));ClientConnectionManager ccm = new ThreadSafeClientConnManager(registry);return new DefaultHttpClient(ccm);} catch (Exception e) {return new DefaultHttpClient();}
}

#21楼

我看到了来自“ emmby”的响应(11年6月16日在21:29回答),项目#4:“创建一个使用内置证书KeyStore的自定义SSLSocketFactory,但由于任何失败而回退到备用KeyStore进行默认验证。”

这是一个简化的实现。 加载系统密钥库并与应用程序密钥库合并。

public HttpClient getNewHttpClient() {try {InputStream in = null;// Load default system keystoreKeyStore trusted = KeyStore.getInstance(KeyStore.getDefaultType()); try {in = new BufferedInputStream(new FileInputStream(System.getProperty("javax.net.ssl.trustStore"))); // Normally: "/system/etc/security/cacerts.bks"trusted.load(in, null); // no password is "changeit"} finally {if (in != null) {in.close();in = null;}}// Load application keystore & merge with systemtry {KeyStore appTrusted = KeyStore.getInstance("BKS"); in = context.getResources().openRawResource(R.raw.mykeystore);appTrusted.load(in, null); // no password is "changeit"for (Enumeration<String> e = appTrusted.aliases(); e.hasMoreElements();) {final String alias = e.nextElement();final KeyStore.Entry entry = appTrusted.getEntry(alias, null);trusted.setEntry(System.currentTimeMillis() + ":" + alias, entry, null);}} finally {if (in != null) {in.close();in = null;}}HttpParams params = new BasicHttpParams();HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);HttpProtocolParams.setContentCharset(params, HTTP.UTF_8);SSLSocketFactory sf = new SSLSocketFactory(trusted);sf.setHostnameVerifier(SSLSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);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();}
}

从JKS转换为BKS的简单模式:

keytool -importkeystore -destkeystore cacerts.bks -deststoretype BKS -providerclass org.bouncycastle.jce.provider.BouncyCastleProvider -providerpath bcprov-jdk16-141.jar -deststorepass changeit -srcstorepass changeit -srckeystore $JAVA_HOME/jre/lib/security/cacerts -srcstoretype JKS -noprompt

*注意:在Android 4.0(ICS)中,信任库已更改,更多信息: http : //nelenkov.blogspot.com.es/2011/12/ics-trust-store-implementation.html

通过HTTPS使用HttpClient信任所有证书相关推荐

  1. iOS开发HTTPS实现之信任SSL证书和自签名证书

    首先来分析一下什么是HTTPS以及了解HTTPS对于iOS开发者的意义 HTTPS 以及SSL/TSL 什么是SSL? SSL(Secure Sockets Layer, 安全套接字层),因为原先互联 ...

  2. http java ssl_使用HttpClient通过HTTPS信任所有证书

    使用HttpClient通过HTTPS信任所有证书 最近发布了一个关于HttpClient过度Https 的问题(在这里找到).我已经取得了一些进展,但我遇到了新的问题.和我的上一个问题一样,我似乎无 ...

  3. fiddler抓取https,提示“CA 根证书不在受信任的存储区域”的解决方法

    背景: fiddler抓取终端https信息,提示:"由于CA 根证书不在"受信任的根证书颁发机构"存储区中,所以它不受信任" 解决方法: 通过在电脑端下载证书 ...

  4. 信任用户证书(CA),实现Android7及以上HTTPS抓包

    信任用户CA,实现Android7及以上HTTPS抓包 Android7以后,系统不再信任用户级的证书,只信任系统级的证书,所以我们要让APP信任用户自己的证书. 注:需要源码,或者反编译 没有源码的 ...

  5. 创建https证书并使谷歌信任该证书

    前言 ​ 最近需要一个https证书进行客户端与服务端的通信,到网上搜了一下,使用java提供的keytool 做了一个证书,发现谷歌浏览器不信任证书,后来根据其他博客整理得出来正确做证书的方法,做完 ...

  6. Android _实现SSL解决不受信任的证书问题

    介绍 网络安全已成为大家最关心的问题. 如果你利用服务器存储客户资料, 那你应该考虑使用 SSL 加密客户跟服务器之间的通讯. 随着这几年手机应用迅速崛起. 黑客也开始向手机应用转移, 原因有下列3点 ...

  7. https、SSL与数字证书介绍

    在互联网安全通信方式上,目前用的最多的就是https配合ssl和数字证书来保证传输和认证安全了.本文追本溯源围绕这个模式谈一谈. 名词解释 首先解释一下上面的几个名词: https:在http(超文本 ...

  8. java ssl https 连接详解 生成证书

    我们在关于Java EE安全的系列文章中,有一篇也详细介绍了如何在Java EE应用中创建SSL连接和证书.正如前面文章提到的,SSL(Secure Sockets Layer,安全套接层)/TLS( ...

  9. Android https 自签名和CA证书验证(基于OkHttp)

    Android HTTPS自签名和CA证书验证(基于OkHttp) HTTPS介绍 CA证书 自签名证书 问题描述 域名校验 OkHttp设置 总结 HTTPS介绍 HTTPS是一种通过计算机网络进行 ...

最新文章

  1. 重磅直播|光学3D测量技术原理及应用
  2. Windows 10 powershell 中文乱码解决方案
  3. 使用 ApiGen 生成开发文档
  4. hihoCoder #1384 : Genius ACM [枚举+倍增]
  5. 在java中arraylist_在Java中将ArrayList添加到另一个ArrayList
  6. jbpm系列之五--使用decision节点判断分支情况
  7. 论定期修改电脑密码的重要性
  8. 数据接口测试工具 Postman 介绍
  9. ebs 供应商地点信息_EBS标准的查看供应商地址
  10. python学到哪知道baseline_Python NLTK学习6(创建词性标注器)
  11. 网页版Rstudio︱RStudio Server多人在线协作开发
  12. 了解更多关于11gR2 diskmon
  13. JSF+Spring+Hibernate整合要点
  14. 2013年最新省市区三级联动mysql数据库_使用PHP+MySql+Ajax+jQuery实现省市区三级联动功能示例...
  15. mac下安装win7虚拟机
  16. 推荐一个好用的搜索微信公众号文章的搜索引擎
  17. MATLAB导入LTspice RAW格式文件教程(绘制波特图)
  18. 【kafka】Kafka 可视化工具Kafka Eagle安装和使用
  19. 基础架构:一条sql语句是如何执行的?
  20. 明日之后什么服务器物品最便宜,明日之后:玩家晒物价最低的服务器,看到uzi标价,观众直接酸了...

热门文章

  1. JavaScript 仿ios滑动选择器
  2. Android stadio litepal
  3. thinkpad alert键一直处于按着的状态
  4. 【剑指offer-Java版】29数组中出现次数超过一半的数字
  5. python实训收获_英泰移动通信:学习Python心得体会
  6. Http和Https对比
  7. iOS架构-静态库.a之依赖第三方静态库.a的制作(8)
  8. BZOJ4754 JSOI2016独特的树叶(哈希)
  9. TP5.0 PHPExcel 数据表格导出导入(引)
  10. centos6.8下安装部署LNMP(备注:nginx1.8.0+php5.6.10+mysql5.6.12)