您的位置:首页 > 理论基础 > 计算机网络

Android ignore https certificate verification 推荐

2012-03-03 23:32 274 查看
通过Https访问的时候经常会遇到"Not trusted Server Certificate"的问题,有人说在3.0上面没有这个问题,可能已经改进了,在2.2及以前的版本中有这个问题。

开始想的是采用安装证书的方法(Trusting SSL certificates),最后也没有成功,不知道是证书的原因还是其他,有人说安装证书只能在WIFI上使用,没有找到官方文档,用户可能在GPRS上使用,只能放弃。

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

EasySSLSocketFactory:

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

}

EasyX509TrustManager:

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.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;

/**
* @author olamy
* @version $Id: EasyX509TrustManager.java 765355 2009-04-15 20:59:07Z evenisse
*          $
* @since 1.2.3
*/
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[],
*      String authType)
*/
public void checkServerTrusted(X509Certificate[] certificates,
String authType) throws CertificateException {
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方法了,希望能有所帮助:)。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Https Android Certificates