Android HttpsUrlConnection HTTPS

Android HttpsUrlConnection HTTPS

HttpsUrlConnection HTTPS通信。

HTTPS(Hyper Text Transfer Protocol Secure)
是一种基于SSL/TLS的HTTP,所有的HTTP数据都是在SSL/TLS协议封装之上进行传输的。
HTTPS协议是在HTTP协议的基础上,添加了SSL/TLS握手以及数据加密传输,也属于应用层协议

SSL/TLS协议的基本过程:
1、客户端向服务器端索要并验证公钥
2、双方协商生成“对话密钥”
3、双方采用“对话密钥”进行加密通信
上面过程的前两布,又称为“握手阶段”

SSL/TLS协议的基本思路是采用公钥加密法:
也就是说,客户端先向服务器端索要公钥,然后用公钥加密信息,服务器收到密文后,用自己的私钥解密。但是这里需要了解两个问题的解决方案。

如何保证公钥不被篡改:
将公钥放在数字证书中。只要证书是可信的,公钥就是可信的。

公钥加密计算量太大,如何减少耗用的时间:
每一次对话(session),客户端和服务器端都生成一个“对话密钥”(session key),用它来加密信息。由于“对话密钥”是对称加密,所以运算速度非常快,而服务器公钥只用于加密“对话密钥”本身,
这样就减少了加密运算的消耗时间

1、HTTPS 访问CA认证的数字证书网站

public void doHttpsConnection(String urls) {
    HttpsURLConnection httpsURLConnection = null;
    BufferedReader reader = null;
    try {
      if(urls != null){
         if(urls.startsWith("https")){
            URL url = new URL(urls);  //CA认证的数字证书网站
            httpsURLConnection = (HttpsURLConnection) url.openConnection();
            httpsURLConnection.setConnectTimeout(5000); //是建立连接的超时时间;
            urlCon.setReadTimeout(5000);  //传递数据的超时时间
            httpsURLConnection.setDoInput(true);
            httpsURLConnection.setUseCaches(false);
            httpsURLConnection.connect();

            reader = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));
            StringBuilder sBuilder = new StringBuilder();
            String line;
            int i=0, lineNum=10;
            while ((line = reader.readLine()) != null && ++i>10) {
               sBuilder.append(line);
           }
           Log.d("doHttpsConnection", "content=" + sBuilder.toString());
         }
      }
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (httpsURLConnection != null) {
            httpsURLConnection.disconnect();
        }
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
doHttpsConnection("https://www.baidu.com/");

2、HTTPS 访问自签名的数字证书网站
HttpsURLConnection配置为信任所有的CA证书:
这种方式很容易的就能访问自签名的HTTPS网站,但是会导致严重的安全问题,如“中间人攻击”。

中间人攻击
虽然上述方案使用了HTTPS,客户端和服务器端的通信内容得到了加密,嗅探程序无法得到传输的内容,但是无法抵挡“中间人攻击”。
例如,在内网配置一个DNS,把目标服务器域名解析到本地的一个地址,然后在这个地址上使用一个中间服务器作为代理,它使用一个假的证书与客户端通讯,
然后再由这个代理服务器作为客户端连接到实际的服务器,用真的证书与服务器通讯。这样所有的通讯内容都会经过这个代理,而客户端不会感知,这是由于客户端不校验服务器公钥证书导致的

1、实现X509TrustManager接口(但实现中跳过客户端和服务器端认证)

public class TrustAllCertsManager implements X509TrustManager { //X590TrustedManager: TrustManager的子接口,管理X509证书,验证远程安全套接字
    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        // Do nothing -> accept any certificates
    }

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType)
            throws CertificateException {
        // Do nothing -> accept any certificates
    }

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

2、HostnameVerifier接口实现

public class VerifyEverythingHostnameVerifier implements HostnameVerifier {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true; //不进行url和服务器主机名的验证
    }
}

3、SSLContext创建、初始化

TrustManager[] trustManager = new TrustManager[] {new TrustEverythingTrustManager()}; // 创建信任所有CA证书的信任管理器数组
SSLContext sslContext = null; //SSLContext 此类的实例表示安全套接字协议的实现,它是SSLSocketFactory、SSLServerSocketFactory和SSLEngine的工厂
try { 
    sslContext = SSLContext.getInstance("SSL");  
    sslContext.init(null, trustManager, new java.security.SecureRandom()); //设置SSLContext的信任管理器
} catch (NoSuchAlgorithmException e) {
    // do nothing
}catch (KeyManagementException e) {
    // do nothing
}
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); //设置HttpsURLConnection类的默认SSLSocketFactory

4、HttpsUrlConnection实例化

public void doHttpsConnection() {
    HttpsURLConnection httpsURLConnection = null;
    BufferedReader reader = null;
    try {
        URL url = new URL("https://kyfw.12306.cn/otn/index/init");  //自签名的HTTPS网站,12306登录界面url
        httpsURLConnection = (HttpsURLConnection) url.openConnection();
        httpsURLConnection.setHostnameVerifier(new VerifyEverythingHostnameVerifier()); //设置HostnameVerifier 

        httpsURLConnection.setConnectTimeout(5000); //是建立连接的超时时间;
        urlCon.setReadTimeout(5000);  //传递数据的超时时间
        httpsURLConnection.setDoInput(true);
        httpsURLConnection.setUseCaches(false);
        httpsURLConnection.connect();

        reader = new BufferedReader(new InputStreamReader(httpsURLConnection.getInputStream()));
        StringBuilder sBuilder = new StringBuilder();
        String line;
        int i=0, lineNum=10;
        while ((line = reader.readLine()) != null && ++i>10) {
            sBuilder.append(line);
        }
        Log.d("doHttpsConnection", "content=" + sBuilder.toString());
    } catch (MalformedURLException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (httpsURLConnection != null) {
            httpsURLConnection.disconnect();
        }
        if (reader != null) {
            try {
                reader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

HttpsURLConnection配置信任指定的CA证书:
为了防止“中间人攻击”,可将服务器端的公钥证书编译到Android应用中(通过配置HttpsUrlConnection的SSLSocketFactory(SSLSocketFactory <- SSLContext <- TrustManager<-KeyStore-

private TrustManager[] createTrustManager() {
    BufferedInputStream inputStream = null;
    try {
        inputStream = new BufferedInputStream(getAssets().open("srca.cer"));  //读取assets存放的服务器公钥证书

        CertificateFactory cf = CertificateFactory.getInstance("X.509"); // 根据公钥证书创建Certificate对象
        Certificate ca = cf.generateCertificate(inputStream);
        Log.e("TrustManager", "ca=" + ((X509Certificate) ca).getSubjectDN());

        KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); // 生成包含当前CA证书的keystore, keystore表示密钥和证书的存储设施
        keyStore.load(null, null);
        keyStore.setCertificateEntry("ca", ca);

        String algorithm = TrustManagerFactory.getDefaultAlgorithm();  // 使用包含指定CA证书的keystore生成TrustManager[]数组
        TrustManagerFactory tmf = TrustManagerFactory.getInstance(algorithm);
        tmf.init(keyStore);
        return tmf.getTrustManagers();
    } catch (CertificateException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (KeyStoreException e) {
        e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } finally {
        if (cerInputStream != null) {
            try {
                cerInputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    return null;
}

3、SSLContext创建、初始化

TrustManager[] trustManager = createTrustManager(); // 创建信任所有CA证书的信任管理器数组
SSLContext sslContext = null;
if (trustManagers == null) {
    Log.e("TAG", "tmf create failed!");
    return;
}else{
    try {
       sslContext = SSLContext.getInstance("SSL"); 
       sslContext.init(null, trustManager, new SecureRandom()); //设置SSLContext的信任管理器
    } catch (NoSuchAlgorithmException e) {
       // do nothing
    }catch (KeyManagementException e) {
       // do nothing
    }
}
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory()); //设置HttpsURLConnection类的默认SSLSocketFactory

4、HttpsUrlConnection实例化,调用上面的doHttpsConnection()函数
doHttpsConnection(“https://kyfw.12306.cn/otn/index/init“); //自签名的HTTPS网站,12306登录界面url

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值