我正在尝试几天以找出如何从服务器获取证书,我们正在进行SSL通信,以便让我识别需要检查其证书的服务器.
关于代码的一些事情,我使用的是httpClIEnt,而且-我不想从认证中创建密钥存储,并将其作为this链接添加到“信任存储”中,还有许多其他建议.
因此,为了获得证书,我要做的是实现X509HostnameVerifIEr,并在其verify()方法中执行以下 *** 作:
session.getPeerCertificates();
但是该功能通过异常:
An exception occurred: javax.net.ssl.SSLPeerUnverifIEdException
这是代码:
import java.io.IOException;import java.security.cert.Certificate;import javax.net.ssl.SSLException;import javax.net.ssl.SSLPeerUnverifIEdException;import javax.net.ssl.SSLSession;import javax.net.ssl.SSLSocket;public class MyHostnameVerifIEr implements ch.boye.httpclIEntandroIDlib.conn.ssl.X509HostnameVerifIEr { @OverrIDe public boolean verify(String hostname, SSLSession session) { Certificate[] certificates; try { certificates = session.getPeerCertificates(); // if connection doesn't contain any certificate - drop it, it might be an Hacker. if (certificates == null || certificates.length == 1) return true; } catch (SSLPeerUnverifIEdException e) { } return true; } @OverrIDe public voID verify(String hostname, SSLSocket socket) throws IOException { socket.getSession().getPeerCertificates(); // exception } @OverrIDe public voID verify(String hostname, String[] arg1, String[] arg2) throws SSLException { } @OverrIDe public voID verify(String arg0, java.security.cert.X509Certificate arg1) throws SSLException { }}
和用法示例:
PoolingClIEntConnectionManager cm = new PoolingClIEntConnectionManager();// Increase max total connection to 10cm.setMaxTotal(GlobalConstants.http_CLIENT_MAX_TOTAL_CONNECTIONS);httpParams httpParameters = new BasichttpParams();int timeoutConnection = CONNECTION_TIMEOUT_MS_DEFAulT;httpconnectionParams.setConnectionTimeout(httpParameters, timeoutConnection);httpconnectionParams.setSoTimeout(httpParameters, timeoutSocket);HostnameVerifIEr hostnameVerifIEr = new MyHostnameVerifIEr();SSLSocketFactory socketFactory = SSLSocketFactory.getSocketFactory();socketFactory.setHostnameVerifIEr((X509HostnameVerifIEr) hostnameVerifIEr);cm.getSchemeRegistry().register(new ch.boye.httpclIEntandroIDlib.conn.scheme.Scheme("https", 443, socketFactory));DefaulthttpClIEnt httpClIEnt = new DefaulthttpClIEnt(cm, httpParameters);
解决方法:
好了朋友们,
这是解决方案,
因此,首先您应该了解TrustManager的工作方式,然后对照TrustManager检查每个认证的ssl通信.现在,默认情况下,系统TrustManager包含所有已通过认证的证书(您可以在“设置”中轻松找到它).
接下来,http通信使用Socket,因此我们需要找到一种方法将TrustManager连接到使用的套接字-您可以在下面找到实现.
因此,为了实际获得证书并将其与本地硬编码证书进行比较,您需要实现TrustManager.
顺便说一句,我知道这很明显,但是无论如何我都会说,永远不要保存硬编码的密码/证书等.始终保存它的SHA1 / SHA256以对抗黑客.
这是代码:
public class x509trustmanager implements x509trustmanager {private final static String TAG = "x509trustmanager";private static final boolean DEAFulT_TRUST_ALL_SSL_CONNECTIONS = true;private x509trustmanager standardTrustManager = null;private boolean trustAllSSLConnections;/** * Constructor for Easyx509trustmanager. */public x509trustmanager(KeyStore keystore) throws NoSuchAlgorithmException, KeyStoreException { trustAllSSLConnections = DEAFulT_TRUST_ALL_SSL_CONNECTIONS; 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];}@OverrIDepublic voID checkClIEntTrusted(X509Certificate[] certificates, String authType) throws CertificateException { standardTrustManager.checkClIEntTrusted(certificates, authType);}/** * verifIEd the server certificate */@OverrIDepublic voID checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException { X509Certificate certificate = certificates[0]; byte[] bytes = certificate.getTBSCertificate(); // Compare your the certificate’s bytes to yours hardcoded certificate. }/** * @see javax.net.ssl.x509trustmanager#getAcceptedissuers() */@OverrIDepublic X509Certificate[] getAcceptedissuers() { return this.standardTrustManager.getAcceptedissuers();}
}
通常,对于每个认证请求,都有一条从顶级认证中心到其他子授权机构(公司,代理…)的认证路径,这就是为什么您的证书可能位于阵列的第一个单元中的原因(I是基于一些测试而不是真正的深入研究来建立这一理论的).
为了将TrustManager连接到套接字,请使用以下代码:
public class SSLSocketFactory implements layeredSocketFactory {private SSLContext sslcontext = null;private static SSLContext createEasySSLContext() throws IOException { try { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, new TrustManager[] { new x509trustmanager(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;}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;}public Socket createSocket() throws IOException { return getSSLContext().getSocketFactory().createSocket();}public boolean isSecure(Socket socket) throws IllegalArgumentException { return true;}public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnkNownHostException { 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(SSLSocketFactory.class));}public int hashCode() { return SSLSocketFactory.class.hashCode();}
}
现在,为了将套接字连接到httpClIEnt,请使用以下代码:
SchemeRegistry schemeRegistry = new SchemeRegistry(); httpParams params = new BasichttpParams(); params.setParameter(ConnManagerPnames.MAX_TOTAL_CONNECTIONS, http_CLIENT_MAX_TOTAL_CONNECTIONS); params.setParameter(ConnManagerPnames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(http_CLIENT_MAX_TOTAL_CONNECTIONS)); params.setParameter(httpProtocolParams.USE_EXPECT_CONTINUE, false); httpProtocolParams.setVersion(params, httpVersion.http_1_1); schemeRegistry.register(new Scheme("https", new SSLSocketFactory(), 443)); schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80)); ClIEntConnectionManager cm = new ThreadSafeClIEntConnManager(params, schemeRegistry); DefaulthttpClIEnt clIEnt = new DefaulthttpClIEnt(cm, params); // enable proxy web deBUGging ("sniffing") ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(clIEnt.getConnectionManager().getSchemeRegistry(), ProxySelector.getDefault()); clIEnt.setRoutePlanner(routePlanner); // disable retrIEs clIEnt.sethttpRequestRetryHandler(new DefaulthttpRequestRetryHandler(0, false)); // setup User-Agent clIEnt.getParams().setParameter(CoreProtocolPnames.USER_AGENT, getAppContext());
不要忘记根据经过认证的通信对其进行测试.
总结以上是内存溢出为你收集整理的android-Https获取服务器证书全部内容,希望文章能够帮你解决android-Https获取服务器证书所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)