Https双向认证Android客户端配置

来源:互联网 发布:网络捕鱼游戏原理 编辑:程序博客网 时间:2024/05/21 06:00

Https双向认证啊  做了两遍,第一遍懵懂状态处于 好不容易做好了,换服务器,一下子懵了,使出浑身解数又找了一遍,这下终于好了  快哭啦快哭了,必须滴要记录一下,以免以后遇到继续懵,这里用retrofit2+okhttp3为例子来简单说明下

先来说说证书:

服务端提供的证书有四个(我这里四个就够用了,有的上面介绍说有一个p12证书,原来提供过,表示没用到,可能是我用的验证方法不一样吧)

转化步骤:

1)生成客户端证书

keytool -genkeypair -alias client -keyalg RSA -validity 3650 -keypass123456 -storepass 123456 -keystore client.jks

这里要说一下,client.jks后端的同事已经提供给我,这一步我就省啦,如果没提供的话 走一步就行啦

2)生成服务端keystore

keytool -genkeypair -alias server -keyalg RSA -validity 3650 -keypass 123456 -storepass123456 -keystore server.keystore

这个也提供啦,我也省了哈

3)导出客户端证书
keytool -export -alias client -file client.cer -keystore client.jks -storepass 123456

这里根据本人理解是将客户端的jks证书导入到服务端cer证书中

4)导出服务端证书
keytool -export -alias server -file server.cer -keystore server.keystore -storepass 123456

这里本人理解是将cer证书导入到keystore中(这里感觉理解的不是很透彻,勿喷)

5)证书交换
将客户端证书导入服务端keystore中,再将服务端证书导入客户端keystore中, 一个keystore可以导入多个证书,生成证书列表。
生成客户端信任证书库(由服务端证书生成的证书库):
    keytool -import -v -alias server -file  server.cer -keystore truststore.jks -storepass 123456

将客户端证书导入到服务器证书库(使得服务器信任客户端证书):
keytool -import -v -alias client -file client.cer -keystore server.keystore -storepass 123456

6)转换jks证书为Android能够识别的BKS证书

将client.jks和truststore.jks通过portecle-1.9软件转换为.bks文件

步骤:打开portecle.jar文件(window系统的,直接打开是压缩包哦,要选择打开方式 用java方式打开,或者直接切换到mac系统转换好了再粘贴回来即可)

注意:我这里转换client.jks的时候回报错的哦

java.security.KeyStoreException: java.io.IOException: Error initialising store of key store: java.security.InvalidKeyException: Illegal key size
这个尚未明白什么意思,就换了一个方法生成client.bks文件了
7)生成客户端bks文件
keytool -importcert -trustcacerts -keystore E:\newkey\client.bks -file E:\keyhttps\server.cer -storetype BKS -provider org.bouncycastle.jce.provider.BouncyCastleProvider
这个要在JDK目录下:C:\Program Files\Java\jdk1.7.0_80\jre\lib\ext中添加bcprov-ext-jdk15on-146.jar包文件(这个根据不同的jdk版本找对应的,这个搜一下就行啦)
8)将client.bks,truststore.bks,以及server.cercopy到工程的Assets下完成验证
9)项目中的配置
Application文件
import android.app.Application;import android.os.Environment;import android.os.Process;import android.util.Log;import com.baidu.mapapi.SDKInitializer;import com.franmontiel.persistentcookiejar.ClearableCookieJar;import com.franmontiel.persistentcookiejar.PersistentCookieJar;import com.franmontiel.persistentcookiejar.cache.SetCookieCache;import com.franmontiel.persistentcookiejar.persistence.SharedPrefsCookiePersistor;import com.zhy.http.okhttp.OkHttpUtils;import com.zhy.http.okhttp.https.HttpsUtils;import com.zhy.http.okhttp.log.LoggerInterceptor;import org.wlf.filedownloader.FileDownloadConfiguration;import org.wlf.filedownloader.FileDownloader;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.util.concurrent.TimeUnit;import javax.net.ssl.HostnameVerifier;import javax.net.ssl.SSLSession;import okhttp3.OkHttpClient;import static android.content.ContentValues.TAG;/** * Created by Jane on 2017/6/23. */public class HNAPPlication extends Application {    private final static String CLIENT_PRI_KEY = "client.bks";    private final static String TRUSTSTORE_PUB_KEY = "truststore.bks";    private final static String SERVER_KEY = "server.cer";    @Override    public void onCreate() {        super.onCreate();        initOkhttp();        // 在使用 SDK 各组间之前初始化 context 信息,传入 ApplicationContext               checkAppReplacingState();    }    private void checkAppReplacingState() {        if (getResources() == null) {            Log.w(TAG, "app is replacing...kill");            Process.killProcess(Process.myPid());        }    }    private void initOkhttp() {        //InputStream [] inputStreams=null;        ClearableCookieJar cookieJar1 = new PersistentCookieJar(new SetCookieCache(), new SharedPrefsCookiePersistor(getApplicationContext()));//        inputStreams = new InputStream[4];//        try {////        inputStreams[0] = getClass().getResourceAsStream("/assets/newkey.cer");//            inputStreams[0] = getAssets().open("newkey.cer");//        } catch (IOException e) {//            e.printStackTrace();//        }        //读取证书        try {            InputStream clientkey = getAssets().open(CLIENT_PRI_KEY);            InputStream serverkey = getAssets().open(TRUSTSTORE_PUB_KEY);            InputStream[] inputStreams = new InputStream[4];//            inputStreams[0] = getClass().getResourceAsStream("/assets/" + SERVER_KEY);                inputStreams[0] = getAssets().open(SERVER_KEY);            HttpsUtils.SSLParams sslParams = HttpsUtils.getSslSocketFactory(inputStreams, clientkey, "Eastcom_1");//        CookieJarImpl cookieJar1 = new CookieJarImpl(new MemoryCookieStore());            OkHttpClient okHttpClient = new OkHttpClient.Builder()                    .connectTimeout(10000L, TimeUnit.MILLISECONDS)                    .readTimeout(10000L, TimeUnit.MILLISECONDS)                    .addInterceptor(new LoggerInterceptor("TAG"))                    .cookieJar(cookieJar1)                    .hostnameVerifier(new HostnameVerifier() {                        @Override                        public boolean verify(String hostname, SSLSession session) {                            return true;                        }                    })                    .sslSocketFactory(sslParams.sSLSocketFactory, sslParams.trustManager)                    .build();            OkHttpUtils.initClient(okHttpClient);        } catch (IOException e) {            e.printStackTrace();        }    }}

HttpsUtil类
public class HttpsUtils{    public static class SSLParams    {        public SSLSocketFactory sSLSocketFactory;        public X509TrustManager trustManager;    }    public static SSLParams getSslSocketFactory(InputStream[] certificates, InputStream bksFile, String password)    {        SSLParams sslParams = new SSLParams();        try        {            TrustManager[] trustManagers = prepareTrustManager(certificates);            KeyManager[] keyManagers = prepareKeyManager(bksFile, password);            SSLContext sslContext = SSLContext.getInstance("TLS");            X509TrustManager trustManager = null;            if (trustManagers != null)            {                trustManager = new MyTrustManager(chooseTrustManager(trustManagers));            } else            {                trustManager = new UnSafeTrustManager();            }            sslContext.init(keyManagers, new TrustManager[]{trustManager},null);            sslParams.sSLSocketFactory = sslContext.getSocketFactory();            sslParams.trustManager = trustManager;            return sslParams;        } catch (NoSuchAlgorithmException e)        {            throw new AssertionError(e);        } catch (KeyManagementException e)        {            throw new AssertionError(e);        } catch (KeyStoreException e)        {            throw new AssertionError(e);        }    }    private class UnSafeHostnameVerifier implements HostnameVerifier    {        @Override        public boolean verify(String hostname, SSLSession session)        {            return true;        }    }    private static class UnSafeTrustManager implements X509TrustManager    {        @Override        public void checkClientTrusted(X509Certificate[] chain, String authType)                throws CertificateException        {        }        @Override        public void checkServerTrusted(X509Certificate[] chain, String authType)                throws CertificateException        {        }        @Override        public X509Certificate[] getAcceptedIssuers()        {            return new java.security.cert.X509Certificate[]{};        }    }    private static TrustManager[] prepareTrustManager(InputStream... certificates)    {        if (certificates == null || certificates.length <= 0) return null;        try        {            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());            keyStore.load(null);            int index = 0;            for (InputStream certificate : certificates)            {                String certificateAlias = Integer.toString(index++);                keyStore.setCertificateEntry(certificateAlias, certificateFactory.generateCertificate(certificate));                try                {                    if (certificate != null)                        certificate.close();                } catch (IOException e)                {                }            }            TrustManagerFactory trustManagerFactory = null;            trustManagerFactory = TrustManagerFactory.                    getInstance(TrustManagerFactory.getDefaultAlgorithm());            trustManagerFactory.init(keyStore);            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();            return trustManagers;        } catch (NoSuchAlgorithmException e)        {            e.printStackTrace();        } catch (CertificateException e)        {            e.printStackTrace();        } catch (KeyStoreException e)        {            e.printStackTrace();        } catch (Exception e)        {            e.printStackTrace();        }        return null;    }    private static KeyManager[] prepareKeyManager(InputStream bksFile, String password)    {        try        {            if (bksFile == null || password == null) return null;            KeyStore clientKeyStore = KeyStore.getInstance("BKS");            clientKeyStore.load(bksFile, password.toCharArray());            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());            keyManagerFactory.init(clientKeyStore, password.toCharArray());            return keyManagerFactory.getKeyManagers();        } catch (KeyStoreException e)        {            e.printStackTrace();        } catch (NoSuchAlgorithmException e)        {            e.printStackTrace();        } catch (UnrecoverableKeyException e)        {            e.printStackTrace();        } catch (CertificateException e)        {            e.printStackTrace();        } catch (IOException e)        {            e.printStackTrace();        } catch (Exception e)        {            e.printStackTrace();        }        return null;    }    private static X509TrustManager chooseTrustManager(TrustManager[] trustManagers)    {        for (TrustManager trustManager : trustManagers)        {            if (trustManager instanceof X509TrustManager)            {                return (X509TrustManager) trustManager;            }        }        return null;    }    private static class MyTrustManager implements X509TrustManager    {        private X509TrustManager defaultTrustManager;        private X509TrustManager localTrustManager;        public MyTrustManager(X509TrustManager localTrustManager) throws NoSuchAlgorithmException, KeyStoreException        {            TrustManagerFactory var4 = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());            var4.init((KeyStore) null);            defaultTrustManager = chooseTrustManager(var4.getTrustManagers());            this.localTrustManager = localTrustManager;        }        @Override        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException        {        }        @Override        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException        {            try            {                defaultTrustManager.checkServerTrusted(chain, authType);            } catch (CertificateException ce)            {                localTrustManager.checkServerTrusted(chain, authType);            }        }        @Override        public X509Certificate[] getAcceptedIssuers()        {            return new X509Certificate[0];        }    }}
Net请求配置
/** * Created by Jane on 2017/6/16. * 网络请求Api */public class NetHttpApi {    private Retrofit retrofit;    //请求超时时间    private static final int REQUEST_TIME = 10;    private static NetHttpApi instance;    private Context context;    private OkHttpClient okHttpClient;    private   InputStream[] inputStreams;    private SSLSocketFactory sslSocketFactory;    /**     * @param urlType url访问地址类型     **/    private NetHttpApi(int urlType, Context context) {        this.context = context;//        //日志显示级别        Gson gson = new GsonBuilder()                .setLenient()                .create();        OkHttpClient client = aa();        if (urlType == Contants.OLD_URL_TYPE) {            retrofit = new Retrofit.Builder().client(client)                    .addConverterFactory(GsonConverterFactory.create(gson))                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                    .baseUrl(Contants.APP_OLD_URL).build();        } else if (urlType == Contants.NEW_URL_TYPE) {            retrofit = new Retrofit.Builder().client(client)                    .addConverterFactory(GsonConverterFactory.create(gson))                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())                    .baseUrl(Contants.APP_URL).build();        }    }    private OkHttpClient aa() {        //日志显示级别        HttpLoggingInterceptor.Level level = HttpLoggingInterceptor.Level.BODY;        //新建log拦截器        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {            @Override            public void log(String message) {                Log.d("vvvvvvvvv", "OkHttp====Message==:" + message);            }        });        loggingInterceptor.setLevel(level);        OkHttpClient okHttpClient = new OkHttpClient.Builder()                .sslSocketFactory(SSLHelper.getSSLCertifcation(context))                .hostnameVerifier(new UnSafeHostnameVerifier())                .addInterceptor(loggingInterceptor)                .build();        return okHttpClient;    }    /**     * 创建单例模式,避免重复创建对象     **/    public static NetHttpApi getInstance(final int urlType, Context context) {//        if (instance == null) {//            synchronized (NetHttpApi.class) {//                if (instance == null) {//                    instance = new NetHttpApi(urlType,context);//                }//            }//        }        NetHttpApi netHttpApi = new NetHttpApi(urlType, context);        return netHttpApi;    }    /**     * 获取一个service对象     */    public <T> T getService(Class<T> service) {        return retrofit.create(service);    }}
SSLHelper
public class SSLHelper {    private final static String CLIENT_PRI_KEY = "client.bks";    private final static String TRUSTSTORE_PUB_KEY = "truststore.bks";    private final static String CLIENT_BKS_PASSWORD = "Eastcom_1";    private final static String TRUSTSTORE_BKS_PASSWORD = "Eastcom_1";    private final static String KEYSTORE_TYPE = "BKS";    private final static String PROTOCOL_TYPE = "TLS";    private final static String CERTIFICATE_STANDARD = "X509";    public static SSLSocketFactory getSSLCertifcation(Context context) {        SSLSocketFactory sslSocketFactory = null;        try {            // 服务器端需要验证的客户端证书,其实就是客户端的keystore            KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);            // 客户端信任的服务器端证书            KeyStore trustStore = KeyStore.getInstance(KEYSTORE_TYPE);            //读取证书            InputStream ksIn = context.getAssets().open(CLIENT_PRI_KEY);            InputStream tsIn = context.getAssets().open(TRUSTSTORE_PUB_KEY);            //加载证书            keyStore.load(ksIn, CLIENT_BKS_PASSWORD.toCharArray());            trustStore.load(tsIn, TRUSTSTORE_BKS_PASSWORD.toCharArray());            ksIn.close();            tsIn.close();            //初始化SSLContext            SSLContext sslContext = SSLContext.getInstance(PROTOCOL_TYPE);            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(CERTIFICATE_STANDARD);            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(CERTIFICATE_STANDARD);            trustManagerFactory.init(trustStore);            keyManagerFactory.init(keyStore, CLIENT_BKS_PASSWORD.toCharArray());            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);            sslSocketFactory = sslContext.getSocketFactory();        } catch (KeyStoreException e) {            e.printStackTrace();        } catch (IOException e) {            e.printStackTrace();        } catch (CertificateException e) {            e.printStackTrace();        } catch (NoSuchAlgorithmException e) {            e.printStackTrace();        } catch (UnrecoverableKeyException e) {            e.printStackTrace();        } catch (KeyManagementException e) {            e.printStackTrace();        }        return sslSocketFactory;    }}
这是配置文件,其他项目类 需要的话  私我