android-Https获取服务器证书

android-Https获取服务器证书,第1张

概述我正在尝试几天以找出如何从服务器获取证书,我们正在进行SSL通信,以便让我识别需要检查其证书的服务器.关于代码的一些事情,我使用的是HttpClient,而且-我不想从认证中创建密钥存储,并将其作为this链接添加到“信任存储”中,还有许多其他建议.因此,为了获得证书,我要做的是实现X5

我正在尝试几天以找出如何从服务器获取证书,我们正在进行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获取服务器证书所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1078238.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存