HTTPS、HTTP1.1与HTTP2的区别、概念和联系(使用golang实现HTTP2服务器)

HTTPS是HTTP的加密传输版本,HTTP2是加密传输协议,所以HTTPS和HTTP2没有本质的联系

HTTPS

因为http的利用明文进行传输的,所以存在不安全性,https使用SSL\TLS协议对http报文进行加密传输

http的默认端口为80,而https的默认端口为443

在讲解https加密传输之前我们还需要先解释公钥和私钥

公钥和私钥

在现代密码体制中加密和解密是采用不同的密钥(公开密钥),也就是非对称密钥密码系统,每个通信方均需要两个密钥,即公钥和私钥,这两把密钥可以互为加解密。公钥是公开的,不需要保密,而私钥是由个人自己持有,并且必须妥善保管和注意保密。

公钥私钥的原则:

一个公钥对应一个私钥。
密钥对中,让大家都知道的是公钥,不告诉大家,只有自己知道的,是私钥。
使用公钥加密的数据必须要使用它对应的那个私钥才能进行解密

http加密传输的过程:
在这里插入图片描述

  1. 首先客户端会向服务器发送一个Client Hello的报文,报文中包含了SSL的版本,加密组件等信息
  2. 然后服务器收到请求会以Server Hello报文作为应答,同时包含服务器的证书
  3. 客户端在接收到Server Hello报文之后会在本地受信任的CA处进行验证服务器的证书是否由受信CA颁发。
  4. 客户端在确定了服务器证书的可靠性之后会根据服务器证书生成客户端的公私钥和会话密钥
  5. 在生成了客户端的公钥和会话密钥之后客户端会使用服务器的公钥对客户端公钥和会话密钥进行加密并发送给服务器
  6. 服务器接收到客户端传输过来的加密公钥和会话密钥之后会使用服务器自己的私钥解密客户端的信息,从而拿到客户端的未经加密的公钥+会话密钥。并同时生成服务器自己的会话密钥
  7. 服务器会使用上一步得到的客户端公钥加密自己的会话密钥,并发送给客户端
  8. 客户端接收到服务器传输过来的加密会话密钥会使用客户端私钥对服务器的会话密钥进行解密从而得到服务器的会话密钥
  9. 现在客户端就会拥有服务器的会话密钥同时服务器也会拥有客户端的会话密钥了
  10. 现在客户端和服务器就可以通过会话密钥进行加密报文传输了

HTTP2

  • HTTP2使用二进制格式非文本格式
  • HTTP2使用一个连接可以实现多路复用
  • HTTP2使用报文头压缩降低了开销
  • 使用HTTP2协议的浏览器必须使用HTTPS进行加密传输

HTTP2.0 的多路复用和 HTTP1.X 中的长连接复用区别
HTTP/1.0:一次请求-响应,建立一个连接,用完关闭;每一个请求都要建立一个连接。

HTTP/1.1:Pipeling(流水线) 解决方式为,若干个请求排队串行化单线程处理,后面的请求等待前面请求的返回才能获得执行机会。一旦有某请求超时等,后续请求只能被阻塞,毫无办法,也就是人们常说的线头阻塞。

HTTP/2:多个请求可同时在一个连接上并行执行。某个请求任务耗时严重,不会影响到其它连接的正常执行。

在这里插入图片描述
HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接,让高带宽也能真正的服务于 HTTP 的性能提升。

HTTP2首部压缩

假定一个页面有 100 个资源需要加载,而每一次请求都有 1kb 的消息头,则至少需要多消耗 100kb 来获取这些消息头。HTTP2.0 可以维护一个字典,差量更新 HTTP 头部,大大降低因头部传输产生的流量。

原理:

HTTP2会维护一份相同的静态字典,包含常见的头部名称,以及特别常见的头部名称与值的组合。
并且会维护一份相同的动态字典,可以动态地添加内容。
在这里插入图片描述

HTTP2的协议磋商

客户端会询问服务是否支持HTTP2,如果不支持就降级为HTTP1.1,流程如下:

客户端首先发起带有HTTP 2.0 upgrade头部的HTTP1.1报文信息
如果服务器拒绝升级就会返回HTTP1.1的报文数据
如果服务器可以升级就会切换到新的分帧

golang实现HTTP2的加密传输


func main() {
	rs1 := &RealServer{Addr: "127.0.0.1:3003"}
	rs1.Run()
	rs2 := &RealServer{Addr: "127.0.0.1:3004"}
	rs2.Run()

	//监听关闭信号
	quit := make(chan os.Signal)
	signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
	<-quit
}

type RealServer struct {
	Addr string
}

func (r *RealServer) Run() {
	log.Println("Starting httpserver at " + r.Addr)
	mux := http.NewServeMux()
	mux.HandleFunc("/", r.HelloHandler)
	mux.HandleFunc("/base/error", r.ErrorHandler)
	server := &http.Server{
		Addr:         r.Addr,
		WriteTimeout: time.Second * 3,
		Handler:      mux,
	}
	go func() {
		http2.ConfigureServer(server, &http2.Server{})
		log.Fatal(server.ListenAndServeTLS(testdata.Path("server.crt"), testdata.Path("server.key")))
	}()
}

func (r *RealServer) HelloHandler(w http.ResponseWriter, req *http.Request) {
	upath := fmt.Sprintf("http://%s%s\n", r.Addr, req.URL.Path)
	io.WriteString(w, upath)
}

func (r *RealServer) ErrorHandler(w http.ResponseWriter, req *http.Request) {
	upath := "error handler"
	w.WriteHeader(500)
	io.WriteString(w, upath)
}

关键的两个函数:
http2.ConfigureServer(server, &http2.Server{})
表示开启http2协议

server.ListenAndServeTLS(testdata.Path(“server.crt”), testdata.Path(“server.key”))
指定TLS的传输方式,并指定证书和私钥

HTTP2验证

我们开启golang的HTTP2协议服务器,然后使用浏览器输入https://127.0.0.1:3003/就可以看到服务器接收到正常的数据
在这里插入图片描述

并且打开chrome开发者工具查看request信息,可以看到传输的头部都是HTTP2的头部

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值