android中使用https是否对服务证书合法性校验的新的体会

package com.cetcs.logreport.utils;

import android.content.Context;

import org.apache.http.conn.ssl.SSLSocketFactory;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.InvalidKeyException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

/**
 *
 * 解析服务器证书的类,对服务器端的证书serv.crt进行解析,其中server.crt文件是使用
 * openssl生成的自签名的证书
* */
public class SSLVerifyLogServerCrtSocketFactory extends SSLSocketFactory {

    private static final String TAG = "SSLTrustAllSocketFactory";
    private SSLContext mCtx;
    private  Context context;

    public SSLVerifyLogServerCrtSocketFactory(String crtName, KeyStore truststore, Context context)
            throws Throwable {
        super(truststore);
        this.context = context;
        try {
            InputStream certInputStream = new BufferedInputStream(context.getAssets().open(crtName));
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            final X509Certificate serverCertificate = (X509Certificate) certificateFactory.generateCertificate(certInputStream);
            mCtx = SSLContext.getInstance("TLS");
            mCtx.init(null, new TrustManager[]{new X509TrustManager() {
                        @Override
                        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {

                        }

                        @Override
                        public void checkServerTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException {
                            if(x509Certificates == null){
                                throw  new IllegalArgumentException("checkServerTrusted x509Certificates is null ");
                            }
                            if(x509Certificates.length < 0){
                                throw  new IllegalArgumentException("checkServerTrusted x509Certificates is null ");
                            }

                            for(X509Certificate cert :x509Certificates){
                                cert.checkValidity();
                                try {
                                    cert.verify(serverCertificate.getPublicKey());
                                } catch (NoSuchAlgorithmException e) {
                                    e.printStackTrace();
                                } catch (InvalidKeyException e) {
                                    e.printStackTrace();
                                } catch (NoSuchProviderException e) {
                                    e.printStackTrace();
                                } catch (SignatureException e) {
                                    e.printStackTrace();
                                }
                            }

                        }

                        @Override
                        public X509Certificate[] getAcceptedIssuers() {
                            return new X509Certificate[0];
                        }
                    }},
                    null);
        } catch (Exception ex) {
        }
    }

    @Override
    public Socket createSocket(Socket socket, String host,
                               int port, boolean autoClose)
            throws IOException, UnknownHostException {
        return mCtx.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return mCtx.getSocketFactory().createSocket();
    }

    //第一个参数是服务器证书的名字例如:server.crt,第二个参数是应用的上下文
    public static SSLSocketFactory getSocketFactory( String crtName,Context context) {
        try {
            if(crtName == null || "".equalsIgnoreCase(crtName)){
                throw  new IllegalArgumentException(" getSocketFactory crtName is null");
            }
            if(context == null){
                throw  new IllegalArgumentException(" getSocketFactory context is null");
            }
            InputStream certInputStream = new BufferedInputStream(context.getAssets().open(crtName));
            CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");
            X509Certificate serverCertificate = (X509Certificate) certificateFactory.generateCertificate(certInputStream);
            //生成一个保护服务器证书的keystore
            String keyStoreType = KeyStore.getDefaultType();
            KeyStore keyStore = KeyStore.getInstance(keyStoreType);
            keyStore.load(null, null);
            String alias = serverCertificate.getSubjectX500Principal().getName();
            keyStore.setCertificateEntry(alias, serverCertificate);

            //生成SSLSocketFactory
            SSLSocketFactory factory = new SSLVerifyLogServerCrtSocketFactory(crtName,keyStore,context);
            return factory;
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return null;
    }

}

需求使用:实现客户端对服务器的校验,需要认证服务器证书的合法性,当https在握手的协议中返回给客户端的证书应该和保存在客户端本地的证书解析出来的域名应该一样,说明服务器返回的证书给保证在本地的证书是一样的,说明服务器是合法的

        try {
            String crtName = "server.crt";
            SSLSocketFactory sf = SSLVerifyLogServerCrtSocketFactory.getSocketFactory(crtName, mContext);
            //对主机的有效域名进行严格校验
            sf.setHostnameVerifier(SSLSocketFactory.STRICT_HOSTNAME_VERIFIER);return new DefaultHttpClient(ccm, params);

其中server.crt就是保存在手机app 例如assert目录下的证书,是app本地保证的证书,这个证书必须和配置到后台例如tomacat服务器中的证书是一模一样,这里为了客户端验证服务器证书的合法性,在手机app客户端保存了一个证书

mContext是activity或者context对应的手机的上下文,如果这里客户端和服务器在建立https的过程中,如果服务器返回给客户端的证书的域名和app本地保存的证书解析出来的域名是一样的,说明服务器是合法的。

如果客户端在和服务器建立https协议的时候,不对服务器的合法性做校验,信任所有的服务器
package com.cetcs.logreport.utils;

/**
 * Created by wei.yuan on 2016/8/2.
 *
 * 该类主要是用于对服务器证书的单项验证
 */

import org.apache.http.conn.ssl.SSLSocketFactory;

import java.io.IOException;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

public class SSLSocketFactoryEx extends SSLSocketFactory {

    SSLContext sslContext = SSLContext.getInstance("TLS");

    public SSLSocketFactoryEx(KeyStore truststore) throws NoSuchAlgorithmException,
            KeyManagementException, KeyStoreException, UnrecoverableKeyException {
        super(truststore);
        // set up a TrustManager that trusts everything
        TrustManager tm = new X509TrustManager() {

            public X509Certificate[] getAcceptedIssuers() {
                //return new X509Certificate[]{};
                return null;
            }

            @Override
            public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
                // TODO Auto-generated method stub

            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
                // TODO Auto-generated method stub

            }
        };

        sslContext.init(null, new TrustManager[] { tm }, new java.security.SecureRandom());
    }

    @Override
    public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
            throws IOException, UnknownHostException {
        injectHostname(socket, host);
        return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
    }

    @Override
    public Socket createSocket() throws IOException {
        return sslContext.getSocketFactory().createSocket();
    }

    private void injectHostname(Socket socket, String host) {
        try {
            Field field = InetAddress.class.getDeclaredField("hostName");
            field.setAccessible(true);
            field.set(socket.getInetAddress(), host);
        } catch (Exception ignored) {
        }
    }
}
使用技巧:
   KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
            trustStore.load(null, null);

            SSLSocketFactory sf = new SSLSocketFactoryEx(trustStore);
            sf.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
这样大体就是一个使用心得
时间: 2024-10-14 12:00:16

android中使用https是否对服务证书合法性校验的新的体会的相关文章

Android 中使用https

去年ios开发强制使用https,而公司的ios 和android 都是使用同一个服务和域名,这样就要求android这边也要使用https 来作为请求. 网上找了很多方法,这里简单记录一下: 这里我是用的是OkHttp,google 最新的文档中虽然也支持了https,但还是okhttp用的方便. 首先我们要把ca颁发 的证书文件放置一份到本地,之后在装个箱 1 public static OkHttpClient client; 2 3 4 /** 5 * 初始化HTTPS,添加信任证书 6

HTTPS理论基础及其在Android中的最佳实践

我们知道,HTTP请求都是明文传输的,所谓的明文指的是没有经过加密的信息,如果HTTP请求被黑客拦截,并且里面含有银行卡密码等敏感数据的话,会非常危险.为了解决这个问题,Netscape 公司制定了HTTPS协议,HTTPS可以将数据加密传输,也就是传输的是密文,即便黑客在传输过程中拦截到数据也无法破译,这就保证了网络通信的安全. 密码学基础 在正式讲解HTTPS协议之前,我们首先要知道一些密码学的知识. 明文: 明文指的是未被加密过的原始数据. 密文:明文被某种加密算法加密之后,会变成密文,从

Android技术18:Android中Adapter类详解

1.Adapter设计模式 Android中adapter接口有很多种实现,例如,ArrayAdapter,BaseAdapter,CursorAdapter,SimpleAdapter,SimpleCursorAdapter等,他们分别对应不同的数据源.例如,ArrayAdater对应List和数组数据源,而CursorAdapter对应Cursor对象(一般从数据库中获取的记录集).这些Adapter都需要getView方法返回当前列表项显示的View对象.当Model发生改变时,会调用Ba

Android开发中实现https校验

在安卓开发中需要自己写代码实现校验公钥的功能 当然,  如果是自己服务器,就不用校验, 如果是别人的服务器,比如银行,就需要校验 在这里, 小编采用从github上下载的开源框架实现,在开源框架中添加部分代码 下载到开源框架后, 在 AsyncHttpClient.java文件中添加 找到215行代码, 在这里添加校验的代码 证书文件需要拷贝到src的根目录 1 //在这里添加一段 代码, 实现 https 连接, 检验 , 主要是去校验 证书的合法性 2 try { 3 InputStream

为你的android App实现自签名的ssl证书(https)

不愿意看啰嗦的可以直接去          实现步骤 最近公司项目用到https的接口形式,对于一般的网络请求 我们用的是http://******      使用的是 代码用来打开一个 http 连接. URL urlConnection = new URL("http://www.codeproject.com/"); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); 不要在 ht

Android中直播视频技术探究之---视频直播服务端环境搭建(Nginx+RTMP)

一.前言 前面介绍了Android中视频直播中的一个重要类ByteBuffer,不了解的同学可以 点击查看 到这里开始,我们开始动手开发了,因为我们后续肯定是需要直播视频功能,然后把视频推流到服务端,本地在进行拉流播放的流程.所以这个过程中,我们需要首先来把服务端这个中间环节的工作搞定,后续再弄推流和拉流功能.现在推流大部分都是使用RTMP/HLS协议的,关于这两个协议的区别: 所以我们服务端搭建就需要用这两个协议,不过本文放心了,不会去手动的编写一套协议代码的,谁叫这个世界属于开源呢? 需要的

Android中使用HTTP服务

转至 http://blog.csdn.net/liuhe688/article/details/6425225 在Android中,除了使用java.net包下的API访问HTTP服务之外,我们还可以换一种途径去完成工作.Android SDK附带了Apache的HttpClient API.Apache HttpClient是一个完善的HTTP客户端,它提供了对HTTP协议的全面支持,可以使用HTTP GET和POST进行访问.下面我们就结合实例,介绍一下HttpClient的使用方法. 我

一个Demo学完Android中所有的服务(转)

说明:这个例子实现了Android中常见的许多服务,下面是实现的截图 接下来,以源代码的方式分析这个例子   1.MainActivity--主界面 这个类主要是实现用户所看到的这个Activity,其中包含了一系列的按钮,用户点击按钮执行相应的动作,所以在这个类中主要是对按钮的定义和对按钮绑定相应的监听器,下面是实现的代码: [java] view plaincopyprint? package lovefang.stadyService; import android.app.Activit

Android中的服务

首先感谢 红茶前辈: http://my.oschina.net/youranhongcha 废话只说一句:android aosp源码庞大,是个大草原,要跑马,请看准方向,本文就是个方向 (我不写长文,也不贪多,可能介绍不清楚,然后就这样,写给懂的人看) android既然分为 c世界 和 java世界,那么服务也从这俩方面介绍咯: c世界服务称为本地服务.(service manager service好特殊) java世界服务(就是zygote,不,应该说SystemServer中初始化的