通過Https通路的時候經常會遇到"Not trusted Server Certificate"的問題,有人說在3.0上面沒有這個問題,可能已經改進了,在2.2及以前的版本中有這個問題。
StackOverflow上也有相關的方案,我整理了一下。
我将注冊的步驟封裝到DefaultHttpClient子類中了,這樣看上去更清晰一些,你也可以
直接執行個體化DefaultHttpClient的方法。
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());
/**
* @author Brant
* @decription
*/
public class SSLHttpClient extends DefaultHttpClient {
@Override
protected ClientConnectionManager createClientConnectionManager() {
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", PlainSocketFactory
.getSocketFactory(), 80));
//443是Https的預設端口,如果網站配置的端口不一樣,這裡要記着改一下
registry.register(new Scheme("https", new EasySSLSocketFactory(), 443));
return new SingleClientConnManager(getParams(), registry);
}
public static SSLHttpClient getInstance() {
SSLHttpClient client = new SSLHttpClient();
client.setCookieStore(mCookie);
return client;
}
import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.scheme.LayeredSocketFactory;
import org.apache.http.conn.scheme.SocketFactory;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
* This socket factory will create ssl socket that accepts self signed
* certificate
*
* @author olamy
* @version $Id: EasySSLSocketFactory.java 765355 2009-04-15 20:59:07Z evenisse
* $
* @since 1.2.3
public class EasySSLSocketFactory implements SocketFactory,
LayeredSocketFactory {
private SSLContext sslcontext = null;
private static SSLContext createEasySSLContext() throws IOException {
try {
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, new TrustManager[] { new EasyX509TrustManager(
null) }, null);
return context;
} catch (Exception e) {
throw new IOException(e.getMessage());
}
private SSLContext getSSLContext() throws IOException {
if (this.sslcontext == null) {
this.sslcontext = createEasySSLContext();
return this.sslcontext;
/**
* @see org.apache.http.conn.scheme.SocketFactory#connectSocket(java.net.Socket,
* java.lang.String, int, java.net.InetAddress, int,
* org.apache.http.params.HttpParams)
*/
public Socket connectSocket(Socket sock, String host, int port,
InetAddress localAddress, int localPort, HttpParams params)
throws IOException, UnknownHostException, ConnectTimeoutException {
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
int soTimeout = HttpConnectionParams.getSoTimeout(params);
InetSocketAddress remoteAddress = new InetSocketAddress(host, port);
SSLSocket sslsock = (SSLSocket) ((sock != null) ? sock : createSocket());
if ((localAddress != null) || (localPort > 0)) {
// we need to bind explicitly
if (localPort < 0) {
localPort = 0; // indicates "any"
}
InetSocketAddress isa = new InetSocketAddress(localAddress,
localPort);
sslsock.bind(isa);
sslsock.connect(remoteAddress, connTimeout);
sslsock.setSoTimeout(soTimeout);
return sslsock;
* @see org.apache.http.conn.scheme.SocketFactory#createSocket()
public Socket createSocket() throws IOException {
return getSSLContext().getSocketFactory().createSocket();
* @see org.apache.http.conn.scheme.SocketFactory#isSecure(java.net.Socket)
public boolean isSecure(Socket socket) throws IllegalArgumentException {
return true;//不判斷socket,直接傳回true
* @see org.apache.http.conn.scheme.LayeredSocketFactory#createSocket(java.net.Socket,
* java.lang.String, int, boolean)
public Socket createSocket(Socket socket, String host, int port,
boolean autoClose) throws IOException, UnknownHostException {
//return getSSLContext().getSocketFactory().createSocket();
//will get java.io.IOException: SSL handshake failure: I/O error
//during system call, Broken pipe
return getSSLContext().getSocketFactory().createSocket(socket, host,
port, autoClose);
// -------------------------------------------------------------------
// javadoc in org.apache.http.conn.scheme.SocketFactory says :
// Both Object.equals() and Object.hashCode() must be overridden
// for the correct operation of some connection managers
public boolean equals(Object obj) {
return ((obj != null) && obj.getClass().equals(
EasySSLSocketFactory.class));
public int hashCode() {
return EasySSLSocketFactory.class.hashCode();
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
* @version $Id: EasyX509TrustManager.java 765355 2009-04-15 20:59:07Z evenisse
public class EasyX509TrustManager implements X509TrustManager {
private X509TrustManager standardTrustManager = null;
* Constructor for EasyX509TrustManager.
public EasyX509TrustManager(KeyStore keystore)
throws NoSuchAlgorithmException, KeyStoreException {
super();
TrustManagerFactory factory = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
factory.init(keystore);
TrustManager[] trustmanagers = factory.getTrustManagers();
if (trustmanagers.length == 0) {
throw new NoSuchAlgorithmException("no trust manager found");
this.standardTrustManager = (X509TrustManager) trustmanagers[0];
* @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
* String authType)
public void checkClientTrusted(X509Certificate[] certificates,
String authType) throws CertificateException {
standardTrustManager.checkClientTrusted(certificates, authType);
* @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
public void checkServerTrusted(X509Certificate[] certificates,
if ((certificates != null) && (certificates.length == 1)) {
certificates[0].checkValidity();
} else {
standardTrustManager.checkServerTrusted(certificates, authType);
* @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
public X509Certificate[] getAcceptedIssuers() {
return this.standardTrustManager.getAcceptedIssuers();
然後直接執行個體化SSLHttpClient就可以想Http一樣執行HttpGet和HttpPost方法了,希望能有所幫助:)。
本文轉自 breezy_yuan 51CTO部落格,原文連結:http://blog.51cto.com/lbrant/795636,如需轉載請自行聯系原作者