Android之Https请求单向验证

最近公司将所有的接口请求方式改为了Https,所以在这记录分享一下。


一、Https有什么优势和劣势。

优势:      

1、使用HTTPS协议可认证用户和服务器,确保数据发送到正确的客户机和服务器;

2、HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,要比http协议安全,可防止数据在传输过程中不被窃取、改变,确保数据的完整性。

3、HTTPS是现行架构下最安全的解决方案,虽然不是绝对安全,但它大幅增加了中间人攻击的成本。


劣势:

1、SSL 证书需要钱。功能越强大的证书费用越高。个人网站、小网站没有必要一般不会用。

2、SSL 证书通常需要绑定 IP,不能在同一 IP 上绑定多个域名。IPv4 资源不可能支撑这个消耗。( SSL 有扩展可以部分解决这个问题,但是比较麻烦,而且要求浏览器、操作系统支持。Windows XP 就不支持这个扩展,考虑到 XP 的装机量,这个特性几乎没用。)

3、HTTPS 连接缓存不如 HTTP 高效,大流量网站如非必要也不会采用。流量成本太高。

4、HTTPS 连接服务器端资源占用高很多,支持访客稍多的网站需要投入更大的成本。如果全部采用 HTTPS,基于大部分计算资源闲置的假设的 VPS 的平均成本会上去。

5、HTTPS 协议握手阶段比较费时,对网站的相应速度有负面影响。如非必要,没有理由牺牲用户体验。

结论:所以Https并不是适用于所有的情况,也不是一定是比http好,所以使用前需要慎重。


二、准备工作

1.cer证书

2.bks证书

三、示例代码

package com.zeepson.smartbox.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.CertificateFactory;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.KeyManagerFactory;

import android.util.Log;

import com.zeepson.smartbox.service.ZeepsonApplication;

public class MyHttpPost {

	public static String sendPost(String stringUrl, String params) {
		
		byte[] bytes = params.toString().getBytes();
		try {
			
			URL url = new URL(stringUrl);
			
			HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
			// 读取服务器要验证的cer证书
			connection.setSSLSocketFactory(setCertificates(ZeepsonApplication.getContext().getAssets().open("server.cer")));
			// 设置不验证服务器,返回true不验证,false为验证,默认为false;也可以根据arg0的值验证或不验证指定服务器;
			connection.setHostnameVerifier(new HostnameVerifier() {
				@Override
				public boolean verify(String arg0, SSLSession arg1) {
					
					return true;
				}
			});
			
			connection.setConnectTimeout(30000);
			connection.setDoInput(true);// 打开输入流,默认情况下是true
			connection.setDoOutput(true);// 打开输出流 ,需要设为true, 默认情况下是false
			connection.setRequestMethod("POST");
			connection.setUseCaches(false);// 使用post方式不能使用缓存
			// 设置请求体类型为文本类型
			connection.setRequestProperty("Content-Type", "application/json");
			// 设置请求体 的长度
			connection.setRequestProperty("Content-Length", String.valueOf(bytes.length));
			// 获得输出流,向服务器写入
			// getOutputStream会隐含的进行connect,所以不用调用connect也可以
			OutputStream outputStream = connection.getOutputStream();
			outputStream.write(bytes);

			int response = connection.getResponseCode();// 获取响应码
			Log.i("-------新httpPost响应码*********************", ">>>>>>>>>>>>" + response);
			if (response == HttpURLConnection.HTTP_OK) {
				InputStream inputStream = connection.getInputStream();// 获取输入流
				BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
				return responseResult(br);// 处理接收到的数据
			}
		} catch (Exception e) {
			e.printStackTrace();
			return "{\"type\":\"error\",\"code\":0,\"message\":\"发送请求出现错误\",\"data\":null}";
		}
		return "{\"type\":\"error\",\"code\":0,\"message\":\"连接超时\",\"data\":null}";
	}
	
	private static String responseResult(BufferedReader br) {
		String line = null;
		StringBuffer sb_response = new StringBuffer();
		try {
			while ((line = br.readLine()) != null) {
				sb_response.append(line);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		String ret = new String(sb_response);
		Log.i("----------------服务器返回值--------------", ret + "");
		return ret;
	}
	
	
	public static SSLSocketFactory setCertificates(InputStream... certificates){
        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){
                    e.printStackTrace() ;
                }
            }

            //取得SSL的SSLContext实例
            SSLContext sslContext = SSLContext.getInstance("TLS");
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.
                    getInstance(TrustManagerFactory.getDefaultAlgorithm());
            trustManagerFactory.init(keyStore);

            //初始化keystore
            KeyStore clientKeyStore = KeyStore.getInstance("BKS");
            clientKeyStore.load(ZeepsonApplication.getContext().getAssets().open("client1.bks"), "123456".toCharArray());

            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
            keyManagerFactory.init(clientKeyStore, "123456".toCharArray());

            // 第一个参数是授权的密钥管理器,用来授权验证。TrustManager[]第二个是被授权的证书管理器,用来验证服务器端的证书。第三个参数是一个随机数值,可以填写null
            sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());
            return sslContext.getSocketFactory() ;

        } catch (Exception e){
            e.printStackTrace();
        }
        return null ;
    }
	
}

结尾:这次只用到了单向验证,下次需要双向验证后面会补上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值