HTTP2.0 HTTPS学习

来源:互联网 发布:十代思域18寸轮毂数据 编辑:程序博客网 时间:2024/06/05 22:32

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 0
原创粉丝点击