HTTP2.0 HTTPS学习

HTTP2.0 HTTPS学习

消除或减少不必要的网络延迟,将需要传输的数据压缩

1、HTTP2.0与 HTTP/1.1 完全语义兼容的基础上,进一步减少了网络延迟
2、HTTP2.0多路复用:
允许同时通过单一的 HTTP/2连接发起多重的请求-响应消息(即可在同一个TCP连接上双向传输数据,从而实现多流并行而不依赖多个TCP连接,实际上HTTP/2 通信都在一个连接上完成,这个连接可以承载任意数量的双向数据流)HTTP/1.1、HTTP1.0 协议中,浏览器针对同一域名的请求限制阻塞问题(浏览器客户端在同一时间,针对同一域名(浏览器或者客户端是根据domain(域名)来建立连接)的请求有一定数量限制,超过限制数目的请求会被阻塞)

多路复用即连接共享:
一个request对应一个stream并分配一个id,一个连接上可以有多个stream,每个stream的frame可以随机的混杂在一起,接收方可以根据stream id将frame再归属到各自不同的request里面。

优先级和请求依赖的机制配合才能解决关键请求被阻塞的问题 — http2.0里的每个stream都可以设置又优先级(Priority)和依赖(Dependency)。优先级高的stream会被server优先处理和返回给客户端,stream还可以依赖其它的sub streams。优先级和依赖都是可以动态调整的。

(原http1.x协议头里可以设置Connection:Keep-Alive。在header里设置Keep-Alive可以在一定时间内复用连接)

HTTP 性能优化:
HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接
减少服务端的链接压力,内存占用更少,连接吞吐量更大,连接的减少使网络拥塞状况得以改善,同时慢启动时间的减少, 使拥塞和丢包恢复速度更快
3、二进制分帧
此为HTTP2.0突破 HTTP1.1 的性能限制,改进传输性能,实现低延迟和高吞吐量的关键
二进制分帧层处于应用层(HTTP/2)和传输层(TCP or UDP)之间
二进制分帧层中,HTTP/2会将所有传输的信息转换为更小的消息和帧(frame),
并对它们采用二进制格式的编码,其中HTTP1.x的首部信息被封装为HEADER frame,而相应的Request Body则封装到DATA frame里面,这也是HTTP2.0兼容HTTP1.x的关键
4、首部压缩
HTTP/1.1并不支持HTTP首部压缩,SPDY使用DEFLATE算法,而HTTP/2使用专门为首部压缩而设计的HPACK算法
5、基于HTTPS的加密协议传输
HTTP2.0使用了tls的拓展ALPN来做协议升级,可通过黑名单机制禁用了不安全的加密算法来加强安全性能,从而大大提高了传输数据的可靠性,同时HTTP2.0也支持明文HTTP传输,而SPDY强制使用HTTPS
6、服务端推送
一种在客户端请求之前发送数据的机制。
服务器推送:服务器可以对客户端的一个请求发送多个响应,
可以缓存!也让在遵循同源的情况下,不同页面之间可以共享缓存资源成为可能。

Android平台http2.0:
它只在新系统下支持,android系统webview从android4.4(KitKat)才改成基于chrome内核的(chrome内核的webview才能支持spdy和http2.0)。
okhttp是同时支持spdy和http2.0,如果使用ALPN,okhttp要求android系统5.0+(实际上,android4.4上就有了ALPN的实现,不过有bug,知道5.0才正式修复)

//数字签名技术实现了身份认证与数据完整性保证: 消息摘要与非对称加密实现
//消息摘要算法保证了数据的完整性

HTTPS:

HTTPS是HTTP over SSL/TLS,HTTP是应用层协议,TCP是传输层协议,在应用层和传输层之间,增加了一个安全套接层SSL/TLS
SSL/TLS层负责客户端和服务器之间的加解密算法协商、密钥交换、通信连接的建立
SSL(Secure Sockets Layer 安全套接层)
TLS(Transport Layer Security 传输层安全),TLS 是SSL 的标准化后的产物

X509证书链,CA根证书,RA中间机构

Https的工作原理;
1、客户端向服务器发起Https请求;
2、服务器响应并下发证书,证书包含有公钥、证书颁发机构、过期时间、对称加密算法种类等信息;
3、客户端接收到证书后,解析证书信息验证是否合法;
4、证书合法客户端解析对称加密算法种类,并生成对应的密钥(对称加密)通过公钥加密给服务器;
5、后面服务器与客户端通讯就采用对称加密进行加解密,密钥只有客户端与服务器知道,只要加密算法够安全,数据就足够安全;

Https和Http的区别:
1、HTTP 的URL 以http:// 开头,而HTTPS 的URL 以https://
HTTP协议运行在TCP之上,,HTTPS运行在SSL/TLS之上,SSL/TLS运行在TCP之上
2、HTTP 传输的内容都是明文、不安全,而HTTPS 对传输的数据进行加密、相对安全
3、HTTP 无需证书,而HTTPS 需要CA机构wosign的颁发的SSL证书
5、HTTP和HTTPS使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443

android https使用:
SSLContext — 负责证书管理和信任管理器,Https可以有证书也可以没有证书
HostnameVerifier — 主机名称校验

使用HttpsURLConnection进行HTTPS通信
1、TrustManger的checkServerTrusted()
2、对服务器证书域名进行强校验或者真正实现HostnameVerifier的verify()方法
使用OKHttp3.0进行HTTPS通信

public final class HTTPSUtils {  
    private  OkHttpClient client;  
    public Context mContext;  

    /初始化HTTPS,添加信任证书 
    public HTTPSUtils(Context context) {  
        mContext = context;  
        X509TrustManager trustManager;  
        SSLSocketFactory sslSocketFactory;  
        final InputStream inputStream;  
        try {  
            inputStream = mContext.getAssets().open("srca.cer"); // 得到证书的输入流  
            try {    
                trustManager = trustManagerForCertificates(inputStream);//以流的方式读入证书  
                SSLContext sslContext = SSLContext.getInstance("TLS");  
                sslContext.init(null, new TrustManager[]{trustManager}, null);  
                sslSocketFactory = sslContext.getSocketFactory();   
            } catch (GeneralSecurityException e) {  
                throw new RuntimeException(e);  
            }  

            client = new OkHttpClient.Builder()  
                    .sslSocketFactory(sslSocketFactory, trustManager)  //https方式 
                    .build();  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  

    public void run() throws Exception {  
        Request request = new Request.Builder()  
                .url("https://kyfw.12306.cn/otn/")  
                .build();  
        //okhttp 异步执行request请求
        client.newCall(request).enqueue(new Callback() {  
            @Override  
            public void onFailure(Call call, IOException e) {  
            }   
            @Override  
            public void onResponse(Call call, Response response) throws IOException {  
                System.out.println(response.body().string());  
            }  
        });  
    }  


    //以流的方式添加信任证书 
    private X509TrustManager trustManagerForCertificates(InputStream in)  
            throws GeneralSecurityException {  
        // 证书工厂
        CertificateFactory certificateFactory = CertificateFactory.getInstance("X.509");  
        Collection<? extends Certificate> certificates = certificateFactory.generateCertificates(in);  
        if (certificates.isEmpty()) {  
            throw new IllegalArgumentException("expected non-empty set of trusted certificates");  
        }  

        // Put the certificates a key store.  
        char[] password = "password".toCharArray(); // Any password will work.  
        // 密钥库
        KeyStore keyStore = newEmptyKeyStore(password);  
        int index = 0;  
        for (Certificate certificate : certificates) {  
            String certificateAlias = Integer.toString(index++);  
            keyStore.setCertificateEntry(certificateAlias, certificate);  
        }  

        // Use it to build an X509 trust manager.  
        // 密钥管理器
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(  
                KeyManagerFactory.getDefaultAlgorithm());  
        keyManagerFactory.init(keyStore, password);  

        // 信任管理器
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(  
                TrustManagerFactory.getDefaultAlgorithm());  
        trustManagerFactory.init(keyStore); //加载密钥库到信任管理器 
        TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();  

        if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) {  
            throw new IllegalStateException("Unexpected default trust managers:"  
                    + Arrays.toString(trustManagers));  
        }  
        return (X509TrustManager) trustManagers[0];  
    }  

    // 生成密钥库 
    private KeyStore newEmptyKeyStore(char[] password) throws GeneralSecurityException {  
        try {  
            KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); 
            // 这里添加自定义的密码,默认  
            InputStream in = null; // 密码文件或字符串, 'null' creates an empty key store.  
            keyStore.load(in, password);  
            return keyStore;  
        } catch (IOException e) {  
            throw new AssertionError(e);  
        }  
    }  
} 

有安全证书的SSLContext:
public static SSLContext getSSLContext() {
    // 生成SSLContext对象
    SSLContext sslContext = SSLContext.getInstance("TLS");
    // 从assets中加载证书
    InputStream inStream = Application.getInstance().getAssets().open("srca.cer");

    // 证书工厂
    CertificateFactory cerFactory = CertificateFactory.getInstance("X.509");
    Certificate cer = cerFactory.generateCertificate(inStream);

    // 密钥库
    KeyStore kStore = KeyStore.getInstance("PKCS12");
    kStore.load(null, null);
    kStore.setCertificateEntry("trust", cer);// 加载证书到密钥库中

    // 密钥管理器
    KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
    keyFactory.init(kStore, null);// 加载密钥库到管理器

    // 信任管理器
    TrustManagerFactory tFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tFactory.init(kStore);// 加载密钥库到信任管理器

    // 初始化
    sslContext.init(keyFactory.getKeyManagers(), tFactory.getTrustManagers(), new SecureRandom());
    return sslContext;
}

//没有安全证书的SSLContext:
//需要两个对象:
//SSLContext + HostnameVerifier(主机名称校验)
public static SSLContext getSLLContext() {
    SSLContext sslContext = null;
    try {
        sslContext = SSLContext.getInstance("TLS");
        sslContext.init(null, new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType)  {}

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) {}

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        }}, new SecureRandom());
    } catch (Exception e) {
        e.printStackTrace();
    }
    return sslContext;
}

private static HostnameVerifier hostnameVerifier = new HostnameVerifier() {
    @Override
    public boolean verify(String hostname, SSLSession session) {
        return true;
    }
};

//
URL url = new URL("http://blog.csdn.net/yanzhenjie1003");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setRequestMethod("GET");

// 1、设置SSLSocketFoactory 需要安全证书
if (urlConnection instanceof HttpsURLConnection) { // 是Https请求
    SSLContext sslContext = SSLContextUtil.getSSLContext(); // 有安全证书的SSLContext
    if (sslContext != null) {
        SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();
        ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);
    }
}

// 2、设置SSLSocketFoactory 不需要安全证书
if (urlConnection instanceof HttpsURLConnection) { // 是Https请求
    SSLContext sslContext = SSLContextUtil.getSSLContext(); //没有安全证书的SSLContext:
    if (sslContext != null) {
        SSLSocketFactory sslSocketFactory = sslContext.getSLLContextNoCertificate(); //没有证书
        ((HttpsURLConnection) urlConnection).setSSLSocketFactory(sslSocketFactory);
        ((HttpsURLConnection) urlConnection).setHostnameVerifier(SSLContextUtil.hostnameVerifier);
    }
}

// 设置属性
urlConnection.setConnectTimeout(8 * 1000);
urlConnection.setReadTimeout(8 * 1000);

int responseCode = urlConnection.getResponseCode();
if (responseCode == 200) { // 请求成功
    InputStream inputStream = urlConnection.getInputStream();
    // 读取结果,发送到主线程
    ...
    inputStream.close();
}
urlConnection.disconnect();
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值