[JavaEE] HTTP/HTTPS

目录

一、HTTP

[1.1 HTTP是什么](#1.1 HTTP是什么)

[1.2 HTTP发展史](#1.2 HTTP发展史)

[1.3 HTTP工作过程](#1.3 HTTP工作过程)

[1.3.1 抓包工具的原理](#1.3.1 抓包工具的原理)

[1.4 HTTP请求格式](#1.4 HTTP请求格式)

1.4.1认识URL

[1.5 HTTP响应格式](#1.5 HTTP响应格式)

[1.6 认识HTTP"方法"(method)](#1.6 认识HTTP"方法"(method))

[1.6.1 GET方法](#1.6.1 GET方法)

[1.6.2 POST方法](#1.6.2 POST方法)

[1.6.3 其他方法](#1.6.3 其他方法)

[1.7 GET 与 POST 的区别](#1.7 GET 与 POST 的区别)

[1.8 认识请求"报头"(header)](#1.8 认识请求"报头"(header))

[1.9 认识响应"报头"(header)](#1.9 认识响应"报头"(header))

[1.10 认识状态码](#1.10 认识状态码)

二、HTTPS

[2.1 HTTPS 是什么](#2.1 HTTPS 是什么)

[2.2 HTTPS 的工作过程](#2.2 HTTPS 的工作过程)

[2.2.1 对称加密](#2.2.1 对称加密)

[2.2.2 非对称加密](#2.2.2 非对称加密)

[2.2.3 中间人攻击](#2.2.3 中间人攻击)

[2.2.3.1 中间人攻击流程](#2.2.3.1 中间人攻击流程)

[2.2.3.2 解决中间人攻击](#2.2.3.2 解决中间人攻击)


一、HTTP

1.1 HTTP是什么

HTTP (全称为"超文本传输协议") 是一种应用非常广泛的 应用层协议,HTTP不仅能传输文本,还能传输图片,视频等其他类型的数据。服务器之间的相互调用,也有很大概率是HTTP。

1.2 HTTP发展史

HTTP诞生于1991年,目前已经发展成为最主流使用的一种应用层协议,最新版的HTTP3版本也在完善中,目前Google/Facebook等公司的产品已经支持了。

HTTP往往是基于传输层的TCP协议实现的(HTTP1.0,HTTP1.1,HTTP2.0均为TCP,HTTP3基于UDP上线)。因为目前我们主要使用的还是HTTP1.0和HTTP2.0,所以我们下文提到的HTTP都以1.1版本为主。

1.3 HTTP工作过程

我们平时打开一个网站,就是通过HTTP协议来传输数据的。

当我们在浏览器中输入一个"网址"(URL)时,浏览器就给服务器发送HTTP请求,并且服务器返回一个HTTP响应。这个响应结果被浏览器解析之后,就展示成我们看到的页面内容(这个过程中浏览器可能会给服务器发送多个HTTP请求,服务器也会返回多个响应,这些响应就包含了页面HTML,CSS,JavaScript,图片,文字等信息。

"超文本"指的是,传输内容不仅仅是文本(比如html,css就是文本),还可以传输一些其他的资源,比如图片,视频,音频等二进制的数据。

实际上,当我们访问一个网页的时候,可能涉及不止一次的HTTP请求/响应的交互过程,我们可以使用抓包工具来查看HTTP具体的工作过程,下方演示使用Fiddle抓包工具。

点击下方按键可以把响应解析成文本内容。

请求和响应本身都是文本,但是因为要节省网络资源,所以响应的就进行了二进制转化。网络传输中"宽带"是一个稀缺资源,为了传输效率更高往往会对数据进行压缩。

发送HTTP请求,就是往TCP socket中按照格式写入字符串,收到HTTP响应,就是从TCP socket中,读出一段字符串再解析。

• 左侧窗口显示了所有的HTTP请求/相应,可以选中某个请求查看详情。

• 右侧上方显示HTTP请求的报文内容(切换到Raw标签页可以看到详细的数据格式)

• 右侧下方显示HTTP请求的响应内容(切换到Raw标签页可以看到详细的数据格式)

• 请求和响应的详细数据,可以通过右下角的View in Notepad通过记事本打开。

1.3.1 抓包工具的原理

FIddler相当于一个"代理",浏览器访问sogou.com时,就会把HTTP请求现发给FIddler,然后FIddler再把请求转发给sogou服务器,当sogou服务器返回响应的时候,也是Fiddler先拿到数据,然后再把数据交给浏览器。

1.4 HTTP请求格式

首行:方法名+URL+HTTP版本

Header:从第二行开始,码号分割键值对;每组属性之间使用\n分割;遇到空行标识Header部分结束。

Body:空行后面的内容都是Body,Body允许为空字符串,如果Body存在,则在Header中会有一个Content-Length属性来表示Body的长度,Content-Type来表示Body中的数据格式。

一般GET方法不携带,当使用POST方法的时候由POST请求携带,一般在登陆账号或者上传文件的时候使用到POST请求。有的请求有body 有的没有,比如说POST请求就有body,很多的时候,一般上传文件的时候HTTP会把二进制进行转码(如果用url encode体积会很大),一般使用base64编码 把二进制转化成文本的形式。

1.4.1认识URL

• https: 协议方案名,常见的由http和https,也有其他类型的(例如访问mysql时会使用jdbc:mysql)

• user:pass 登录信息,现在的网站进行身份验证一般不通过URL进行。

www.example.jp:80 服务器地址,也可以是域名,数字是服务器端口号。端口号如果不写,根据协议类型自动分配,如果是http协议就是80端口,https协议就是443端口。

• dir/index.htm 带层次的文件路径

• uid=1 查询字符串(query string).本质是一个键值对结构,键和值之间使用=分割,键值对之间使用&分割。

• #ch1 片尾标识,主要用于页面内的跳转

关于 query string

query string 中的内容是键值对结构,其中 key 和 value 的取值个数,完全都是程序员自己约定的,我们可以通过这样的方式来定制传输我们需要的信息给服务器。

关于 URL encode

像/ ? : 等这样的字符,已经被url当做特殊意义理解了,因此这些字符不能随意出现,必须先对特殊字符进行转义。

1.5 HTTP响应格式

HTTP响应

首行:HTTP版本 状态码 状态码的描述,使用空格分隔。

200是最常见的状态码,2开头表成功,4开头表自己的原因,5开头表服务器原因,302表示跳转。

Header:请求的属性,第二行开始,冒号分割键值对,每组属性之间使用\n分割,遇到空行标识Header部分结束。

Body:空行后面的内容都是Body,Body允许为空字符串,如果Body存在,则在Header中会有一个Content-Length属性来表示Body的长度,Content-Type来表示Body中的数据格式。如果服务器返回了一个html页面,那么html页面内容就是在body中。

协议格式总结:

1.6 认识HTTP"方法"(method)

HTTP的方法

1.6.1 GET方法

GET是最常用的HTTP方法,常用于获取服务器上的某个资源。在浏览器中直接输入URL,此时浏览器就会发送一个GET请求,另外,HTML中的link,img,script等标签也会发送GET请求。

GET请求的特点

首行第一部分位GET,URL的 query string 可以为空,也可以不为空。header 部分有若干个键值对结构,body 部分为空。实际的URL长度取决于浏览器的实现 和 HTTP 服务器端的实现。

1.6.2 POST方法

POST方法也是一种常见的方法,多用于提交用户输入的数据给服务器(例如登录页面),也常用在用户上传文件的请求。可以通过HTML中的form标签可以构造POST请求,或者使用JavaScript的 ajax 也可以构造POST请求。

POST请求的特点

首行第一部分为 POST,URL 的 query string 一般为空,header 部分有若干个键值对结构,body 的部分一般不为空,body 内的数据格式通过 header 中的 Content-Type 指定,body 长度由 header 中的 Content-Length 指定。

1.6.3 其他方法

PUT 与 POST 相似,只是具有幂等特性,一般用于更新

DELETE 删除服务器指定资源

OPTIONS 返回服务器所支持的请求方法

HEAD 类似于GET,只不过响应本体不返回,只会返回响应头

TRACE 回显服务器端收到的请求,测试的时候也会用到这个

CONNECT 预留,暂无使用

1.7 GET 与 POST 的区别

• 语义不同:GET一般用于获取数据,POST一般用于提交数据

• GET 的 body 一般为空,POST 请求一般是不幂等的

• GET可以被缓存,POST不能被缓存

补充说明,GET 和 POST 没有本质区别。

• 关于语义:GET 可以用于提交数据,POST 也可以用于获取数据

• 关于幂等性:标准建议 GET 实现为幂等的,实际开发中 GET 也不必完全遵守这个规则

• 关于安全性:有些资料说"POST"比"GET"安全,这样的说法是不科学的,安全取决于前端传输密码登敏感信息时是否进行加密,和 GET POST 无关。

• 关于数据传输量:标准没有规定 GET 的 URL 的长度,也没有规定 POST 的 body 长度,传输数据量多少,完全取决于不同浏览器和不同服务器之间的实现区别。

• 关于传输数据类型:GET 的 query string 虽然无法直接传输 二进制数据,但是可以针对二进制数据 进行 url encode。

1.8 认识请求"报头"(header)

• HOST 表示服务器主机的地址和端口

• Content-Length 表示 body 中的数据长度

• Content-Type 表示请求的 body 中的数据格式

• User-Agent(简称UA) 表示浏览器/操作系统的属性,UA还能统计数据,统计数据主要通来区分PC和移动端。

例如:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/91.0.4472.77 Safari/537.36

其中 Windows NT 10.0; Win64; x64 表示操作系统信息,AppleWebKit/537.36 (KHTML, like Gecko)Chrome/91.0.4472.77 Safari/537.36 表示浏览器信息。

• Refer 表示这个页面是从哪个页面跳转过来的 例如:

Referer: https://gitee.com/login?redirect_to_url=%2F

如果直接在浏览器中输入URL,或者直接通过收藏夹访问页面时是没有Refer的。

• Cookie

Cookie 中储存了一个字符串,这个数据可能是客户端自行通过JS写入的,也有可能来自于服务器(服务器在第一次传送HTTP响应时, HTTP 响应的 header 中通过 Set-Cookie字段给浏览器返回数据)

可以通过这个字段实现"身份标识"的功能,每个不同域名下都可以有不同的Cookie,不同网站之间的Cookie并不冲突。

Cookie 是键值对结构,使用;来分割键值对,使用=来分隔键和值,含义都是程序员自定义的

第一次对服务器发送请求的时候,服务器会返回一个或多个Set-Cookie这样的header,会把cookie通过键值对,设置到电脑硬盘上,因为缓存容易丢,关电脑 掉电都会没,但是并不是谁都可以访问 电脑硬盘,需要获得专门安全机构所颁发的证书才可以。

Cookie 按照域名来分类,访问哪个域名,就把域名下的cookie带入到对服务器发送的请求,客户端和服务器端都需要cookie,功能并不一定一样。

可以通过抓包观察页面登陆的过程(以码云为例)

(1) 清除之前的cookie

(2) 登录操作

登录请求

登录响应

可以看到,响应中包含了3个 Set-Cookie 属性。其中我们重点关注第三个,里面包含了一个

gitee-session-n 这样的属性,属性值是一串很长的加密之后的信息,这个信息就是用户当前登录的身份标识,也称为 "令牌(token)"。

(3)访问其他页面

登陆成功之后,此时可以看到后续访问码云其他页面(比如个人主页),请求中就会带着刚才获取到的Cookie信息。

请求中你的 Cookie 字段也包含了一个 gitee-session-n 属性,里面的值和刚才服务器返回的值相同,后续只要访问 gitee 这个网站,就会一直带着这个令牌,知道令牌过期/下次重新登陆,每一次登陆,令牌都是随机生成不一样的。

1.9 认识响应"报头"(header)

Content-Type

相应中的Content-Type 常见取值有以下几种:

• text/html: body 数据格式是 HTML

• text/css: body 数据格式是 CSS

• application/javascript:body数据格式是 JavaScript

• application/json: body数据格式是 JSON

1.10 认识状态码

状态码表示访问一个页面的结果。(是访问成功,还是失败,还是一些其他情况....)

200OK

这是一个最常见的状态码,表示访问成功

404 Not Found

没有找到资源

浏览器输入一个 URL ,目的就是为了访问对方服务器上的一个资源,如果这个 URL 标识的资源不存在,那么就会出现 404

403 Forbidden

表示访问被拒绝,有的页面通常需要用户具有一定的权限才能访问(登录后才能访问),如果用户没有登录直接访问,就容易见到403。

比如你在访问一个别人的私有码云的时候就会抛出这个异常

405 Method Not Allowed

前面我们已经学习了 HTTP 中所支持的方法,有GET, POST, PUT, DELETE 等。

但是对方的服务器不一定都支持所有的方法(或者不允许用户使用一些其他的方法)。

500 Internal Server Error

服务器内部初现错误,一般是服务器的代码执行过程中遇到了一些特殊的情况(服务器异常崩溃)会产生这个状态码。

咱们平时使用的网站很少会出现 500(但是偶尔也会看到)

504 Gateway Timeout

当服务器负载比较大的时候,服务器处理单挑请求的时候消耗的时间就会很长,就可能会导致出现超的情况。

这种情况比较容易在 双十一等"秒杀"场景中出现。

302 Move temporarily

临时重定向

在登录页面中经常会见到302,用于实现登录成功后自动跳转到主页,响应报文中的 header 部分会包含一个 Location 字段,表示要跳转到哪个页面。

301 Moved Permanently

永久重定向,当浏览器收到这种响应的时候,后续的请求都会被自动改成新的地址。301也是通过Location 字段来表示要重定向到的新地址。

状态码小结

二、HTTPS

2.1 HTTPS 是什么

HTTPS 也是一个应用层协议,是在 HTTP 协议的基础上引入了一个加密层。HTTP 协议内容就是按照文本的方式明文传送的,这就导致在传输过程中会出现一些被篡改的情况。

"运营商劫持"

下载一个天天动听,未被劫持的效果,点击下载,就会跳出天天动听的下载链接。

已经被劫持的效果,点击下载,就会弹出QQ浏览器的下载链接

由于我们通过 网络传输的任何数据包都会经过运营商的 网络设备(路由器,交换机等),俺么运营商就能解析出你传输的数据内容,并进行篡改。

我们可以思考一下,不止运营商可以劫持,黑客也可以用类似的手段进行劫持,来窃取用户的隐私信息,或者篡改内容。在互联网上,明文传输是比较危险的事情,HTTPS 就是在 HTTP 的基础上进行了加密,进一步来保证用户的信息安全。

明文:要传输的原始数据

密文:把明文加密之后的数据

加密:明文->密文

解密:密文->明文

密钥:进行加密和解密的重要数据/解密工具

2.2 HTTPS 的工作过程

既然要保证数据安全,就需要进行"加密"。网络传输中不再直接传输明文了,而是加密之后的密文。加密的方式有很多种,但是整体可以分为两大类: 对称加密非对称加密

2.2.1 对称加密

对称加密其实就是通过同一个"密钥",把明文加密成密文,并且也能把密文解密成明文。

引入对称加密之后,即使数据被拦截,由于黑客不知道密钥是啥,因此就无法进行加密,也就不知道请求的真实内容是什么了。

但是服务器同一时刻 可以给很多客户端提供服务,这么多客户端,每个人用的秘钥都必须是不同的,因此服务器就要维护每个客户端 和 每个密钥之间的关联关系,是一个很麻烦的事。

比较理想的做法,就是能在客户端和服务器建立连接的时候,双方协商确定这次的密钥是啥~

但是如果这样把密钥直接发送给服务器,黑客也会受到你发送的密钥,之后的加密就如同虚设了。

所以我们需要对我们的 对称密钥 进行加密。

2.2.2 非对称加密

非对称加密要用到两个密钥,一个叫做"公钥",一个叫做"私钥"。公钥和私钥是配对的,最大的缺点就是**运算速度非常慢,**比对称加密要慢很多,公钥私钥都可以用来加密和解密。

• 通过公钥对明文加密,变成密文

• 通过私钥对密文解密,变成明文

也可以反着来

• 通过私钥对明文加密,变成密文

• 通过公钥对密文解密,变成明文

• 客户端在本地生成对称密钥,通过公钥加密,发送给服务器。由于中间的网络设备没有私钥,即使截获了数据也无法还原出 原文,也就无法获取到对称密钥。

• 服务器通过私钥解密,还原出客户端发送的对称密钥,并且使用这个对称密钥加密给客户端返回相应数据。

• 后续客户端和服务器的通信都只用对称加密即可,由于该密钥只客户端和福诶我两个主机知道,其他主机/设备 不知道密钥即使截获数据也没有意义。

2.2.3 中间人攻击

黑客可以使用中间人攻击,获取到对称密钥

2.2.3.1 中间人攻击流程

1、服务器有 非对称加密算法 的公钥 pub1 ,私钥 pri1

2、中间人有 非对称加密算法 的公钥 pub2 ,私钥 pri2

3、客户端向服务器发送请求,服务器明文传送 公钥 pub1 给客户端。

4、黑客劫持 具有 pub1 的明文,并且把明文中的 公钥 pub1 改成 自己的公钥 pub2

5、中间人返回给 客户端带有公钥 pub2 的明文,让客户端相信自己是 服务器。

6、客户端分辨不出来,传输带有 pub2 公钥的业务数据,中间人通过私钥 pri2 解析之后,使用公钥 pub1 加密之后发送给服务器,让服务器认为自己是客户端。

7、服务器分辨不出来,传输带有私钥 pri1 的业务数据,中间人用公钥 pub1 解密之后,使用私钥 pri2 加密之后发送给客户端。

8、至此,客户端和服务器所发送的数据在黑客眼前一览无余。

2.2.3.2 解决中间人攻击

服务器端在使用 HTTPS 前,需要向CA机构申领一份数字证书,数字证书里面含有证书的申请者信息、公钥信息等。服务器把证书传输给浏览器,浏览器从证书里获取公钥,证书就好比身份证,证明服务端公钥的权威性。

这个 证书 可以理解成是一个结构化的字符串,里面包含了以下信息

• 证书发布机构

• 证书有效期

• 公钥

• 证书所有者

• 签名

• ......

需要注意的是:申请证书的时候,会同时生成一堆密钥对,即公钥和私钥。这对密钥对就是用来在网络通信中进行文明加密以及数字签名的。

理解数据签名

签名的形成是局域 非对称加密算法的。当服务端申请CA证书的时候,CA机构会对该服务器进行审核,并专门位该网站形成数字签名,过程如下:

1、CA机构拥有非对称加密的 私钥 A 和 公钥 A#

2、CA机构对服务端申请的证书明文数据进行hash,形成数据摘要

3、然后对数据摘要用CA 私钥 A# 加密,得到数字签名S

服务端申请的整数和数字签名S共同组成了数字证书,这样一份数字证书就可以颁发给服务端了。

这样当客户端收到这个证书之后,会对证书进行校验(防止证书是假的)

1、首先会判定证书的有效期是否过期

2、判定证书的发布机构是否收到信任

3、验证证书是否被篡改,从系统中拿到该证书发布机构的公钥,对签名解密并计算校验和,得到hash1;然后计算整个证书的校验和得到 hash2;对比 hash1 和hash2 是否相等,如果相等,则说明证书没被篡改过。

=========================================================================

如果对你有帮助的话,给博主一个三连吧,这对博主真的很重要 ( ´•̥̥̥ω•̥̥̥` )

相关推荐
明月看潮生26 分钟前
青少年编程与数学 02-003 Go语言网络编程 15课题、Go语言URL编程
开发语言·网络·青少年编程·golang·编程与数学
‍。。。1 小时前
使用Rust实现http/https正向代理
http·https·rust
龙哥说跨境1 小时前
如何利用指纹浏览器爬虫绕过Cloudflare的防护?
服务器·网络·python·网络爬虫
懒大王就是我2 小时前
C语言网络编程 -- TCP/iP协议
c语言·网络·tcp/ip
Elaine2023912 小时前
06 网络编程基础
java·网络
海绵波波1073 小时前
Webserver(4.3)TCP通信实现
服务器·网络·tcp/ip
热爱跑步的恒川6 小时前
【论文复现】基于图卷积网络的轻量化推荐模型
网络·人工智能·开源·aigc·ai编程
云飞云共享云桌面7 小时前
8位机械工程师如何共享一台图形工作站算力?
linux·服务器·网络
音徽编程9 小时前
Rust异步运行时框架tokio保姆级教程
开发语言·网络·rust
幺零九零零10 小时前
【C++】socket套接字编程
linux·服务器·网络·c++