【Android】支持https接口调用的简单证书校验

我们在做https接口支持时,用到了X509证书。然后针对X509的证书验证,线下环境不做校验,线上环境仅仅做单向的hostname校验。完善的校验应该包括客户端和服务端的证书校验。

package com.xxx.utils;

import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateParsingException;
import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class HttpsTrustManager implements X509TrustManager {

    private static TrustManager[]          trustManagers;
    private static final X509Certificate[] _AcceptedIssuers = new X509Certificate[] {};

    @Override
    public void checkClientTrusted(X509Certificate[] x509Certificates,
                                   String s) throws java.security.cert.CertificateException {
        //验证客户端证书,不通过则抛出异常
    }

    @Override
    public void checkServerTrusted(X509Certificate[] x509Certificates,
                                   String s) throws java.security.cert.CertificateException {
        //验证服务端证书,不通过则抛出异常
    }

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return _AcceptedIssuers;
    }

    public static void allowAllSSL() {
        HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
            @Override
            public boolean verify(String hostname, SSLSession session) {
                // FIXME 线上要做HTTPS证书信息验证
                boolean isTrust = false;
                //如果线下则默认不校验,isOnline自己做控制
                if (!isOnline) {
                    isTrust = true;
                    LogUtil.d("线下环境,证书不校验。");
                } else {
                    try {
                        //获得证书
                        Certificate[] certificates = session.getPeerCertificates();
                        if (certificates != null && certificates.length > 0) {
                            Certificate certificate = certificates[0];
                            //做X509证书信息获取
                            if (certificate instanceof X509Certificate) {
                                X509Certificate x509Certificate = (X509Certificate) certificate;
                                Collection> subjectAlternativeNames = x509Certificate
                                    .getSubjectAlternativeNames();
                                //获得证书信息
                                String names = Arrays
                                    .deepToString(subjectAlternativeNames.toArray());
                                //校验host信息
                                isTrust = names.contains(hostname);
                            }
                        }
                    } catch (SSLPeerUnverifiedException e) {
                        LogUtil.e("on error when verify SSL." + e.getMessage());
                    } catch (CertificateParsingException e) {
                        LogUtil.e("on error when verify SSL." + e.getMessage());
                    }
                }
                if (!isTrust) {
                    LogUtil.d("证书校验不通过,请核查~(hostname=" + hostname + ")");
                }
                return isTrust;
            }
        });

        SSLContext context = null;
        if (trustManagers == null) {
            trustManagers = new TrustManager[] { new HttpsTrustManager() };
        }

        try {
            context = SSLContext.getInstance("TLS");
            context.init(null, trustManagers, new SecureRandom());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyManagementException e) {
            e.printStackTrace();
        }

        HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
    }

}

然后在网络请求之前调用如下代码:

        //添加https支持
        HttpsTrustManager.allowAllSSL();

你可能感兴趣的:(Android,资源备份,JAVA)