【Java】应用层协议HTTP和HTTPS

HTTP和HTTPS协议

  • HTTP
    • HTTP协议的工作过程
    • HTTP协议格式
      • 抓包工具
      • 抓包结果
    • HTTP请求(Request)
      • URL
      • 方法
        • GET方法
        • POST请求
        • 其他方法
      • 报头(header)
        • Host
        • Content-length
        • Content-Type
        • User-Agent
        • Referer
        • Cookie
      • 正文(body)
    • HTTP响应
      • HTTP状态码
      • 响应报头(header)
      • 响应正文(body)
    • 通过form表单构造HTTP请求
      • form发送GET请求
      • form发送POST请求
    • 通过ajax构造HTTP请求
      • 发送请求
    • 通过第三方工具构造HTTP请求
  • HTTPS
    • 加密
    • HTTPS的工作过程
      • 对称加密
      • 非对称加密
      • 证书
        • 数据摘要和签名
    • 总结

HTTP

HTTP (全称为 “超文本传输协议”) 是一种应用非常广泛的 应用层协议.

HTTP 往往是基于传输层的 TCP 协议实现的. (HTTP1.0, HTTP1.1, HTTP2.0 均为TCP, HTTP3 基于 UDP
实现)

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

所谓 “超文本” 的含义, 就是传输的内容不仅仅是文本(比如 html, css 这个就是文本), 还可以是一些
其他的资源, 比如图片, 视频, 音频等二进制的数据

HTTP协议的工作过程

当我们在浏览器中输入一个 “网址”, 此时浏览器就会给对应的服务器发送一个 HTTP 请求. 对方服务器收
到这个请求之后, 经过计算处理, 就会返回一个 HTTP 响应
【Java】应用层协议HTTP和HTTPS_第1张图片
事实上, 当我们访问一个网站的时候, 可能涉及不止一次的 HTTP 请求/响应 的交互过程.

HTTP协议格式

抓包工具

抓包工具Fiddler 相当于一个 “代理”.
浏览器访问 sogou.com 时, 就会把 HTTP 请求先发给 Fiddler, Fiddler 再把请求转发给 sogou 的服务器.
当 sogou 服务器返回数据时, Fiddler 拿到返回数据, 再把数据交给浏览器.
因此 Fiddler 对于浏览器和 sogou 服务器之间交互的数据细节, 都是非常清楚的.
【Java】应用层协议HTTP和HTTPS_第2张图片

抓包结果

我此处抓到了我访问bilibili主页时的HTTP请求
【Java】应用层协议HTTP和HTTPS_第3张图片

分析HTTP报文结构

首行:方法+url+HTTP的版本
Header:请求的属性,冒号分隔的键值对,每组属性之间使用\n分隔,遇到空行表示Header部分结束
Body:空行后面的内容都是body,我此处抓的包body部分为空,body字符串允许为空,如果body存在,则在Header中会有一个属性Content-Length来表示body的长度

分析HTTP响应

【Java】应用层协议HTTP和HTTPS_第4张图片

首行:版本号+状态码+状态码解释
Header:请求的属性,冒号分隔的键值对,每组属性之间使用\n分割,遇到空行表示Header部分结束
Body:空行后面的内容都是Body,Body允许为空字符串则在Header中会有一个Content-Length属性来标识Body的长度; 如果服务器返回了一个html页面, 那么html页面内容就是在body中,此处访问bilibili主页就返回了bilibili的主页html

为什么HTTP报文中要存在空行

因为HTTP协议中并没有规定报头部分的键值对有多少个,空行就相当于是"报头的结束标记"或者是"报头和正文之间的分隔符"
HTTP协议在传输层依赖TCP协议,TCP协议是面向字节流的,如果没有这个空行,就会出现粘包问题

HTTP请求(Request)

URL

平时我们俗称的 “网址” 其实就是说的 URL (Uniform Resource Locator 统一资源定位符).
互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它.
【Java】应用层协议HTTP和HTTPS_第5张图片

http:协议方案名,常见的有http和https,也有其他的类型(例如访问mysql时用的jdbc)
user:pass : 登陆信息. 现在的网站进行身份认证一般不再通过 URL 进行了. 一般都会省略
v.bitedu.vip : 服务器地址. 此处是一个 “域名”, 域名会通过 DNS 系统解析成一个具体的 IP 地址. (通过 ping 命令可以看到, v.bitedu.vip 的真实 IP 地址为 118.24.113.28 )
端口号: 上面的 URL 中端口号被省略了. 当端口号省略的时候, 浏览器会根据协议类型自动决定使用哪个端口. 例如 http 协议默认使用 80 端口, https 协议默认使用 443 端口.
带层次的文件路径.
查询字符串(query string). 本质是一个键值对结构. 键值对之间使用& 分隔. 键和值之间使用 = 分隔.
片段标识:片段标识主要用于页面内跳转.

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

URL 中的可省略部分

协议名: 可以省略, 省略后默认为 http://
ip 地址 / 域名: 在 HTML 中可以省略(比如 img, link, script, a 标签的 src 或者 href 属性). 省略后表示服务器的 ip / 域名与当前 HTML 所属的 ip / 域名一致.
端口号: 可以省略. 省略后如果是 http 协议, 端口号自动设为 80; 如果是 https 协议, 端口号自动设为 443.
带层次的文件路径: 可以省略. 省略后相当于 / . 有些服务器会在发现 / 路径的时候自动访问/index.html
查询字符串: 可以省略
片段标识: 可以省略

关于 URL encode
像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现.
比如, 某个参数中需要带有这些特殊字符, 就必须先对特殊字符进行转义.

一个中文字符由 UTF-8 或者 GBK 这样的编码方式构成, 虽然在 URL 中没有特殊含义, 但是仍然需 要进行转义. 否则浏览器可能把
UTF-8/GBK 编码中的某个字节当做 URL 中的特殊符号.

转义的规则如下: 将需要转码的字符转为16进制,然后从右到左,取4位(不足4位直接处理),每2位做一位,前面加上%,编码成%XY格式

方法

【Java】应用层协议HTTP和HTTPS_第6张图片

GET方法

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

GET请求的特点

首行的第一部分为GET
URL的query string可以为空,也可以不为空
header部分有若干个键值对结构
body部分为空

POST请求

POST方法也是一种常见的方法,多用于提交用户输入的数据给服务器(例如登陆页面)
通过HTML中的form标签可构造POST请求,或者使用JavaSciipt的ajax也可以构造POST请求
【Java】应用层协议HTTP和HTTPS_第7张图片
POST请求的特点

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

GET和POST的区别

语义不同:GET一般用于获取数据,POST一般用于提交数据
GET的body一般为空,需要传递的数据通过query string传递,POST的query string一般为空,需要传递的数据通过body
GET 请求一般是幂等的, POST 请求一般是不幂等的. (如果多次请求得到的结果一样, 就视为请
求是幂等的).
GET 可以被缓存, POST 不能被缓存. (这一点也是承接幂等性).

其他方法

PUT 与 POST 相似,只是具有幂等特性,一般用于更新
DELETE 删除服务器指定资源
OPTIONS 返回服务器所支持的请求方法
HEAD 类似于GET,只不过响应体不返回,只返回响应头
TRACE 回显服务器端收到的请求,测试的时候会用到这个
CONNECT 预留,暂无使用

报头(header)

header 的整体的格式也是 “键值对” 结构.
每个键值对占一行. 键和值之间使用分号分割.

Host

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

Content-length

表示body中的数据长度

Content-Type

表示请求的body中的数据格式

常见选项:

  • application/x-www-form-urlencoded:form表单提交的数据格式,此时body的格式形如

title=test&content=hello

  • multipart/form-data:form 表单提交的数据格式(在 form 标签中加上enctyped=“multipart/form-data” . 通常用于提交图片/文件.)

  • application/json:数据为json格式 格式形如

{“username”:“123456789”,“password”:“xxxx”,“code”:“jw7l”,“uuid”:“d110a05ccde64b16a861fa2bddfdcd15”}

User-Agent

表示浏览器/操作系统的属性,形如

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 表示浏览器信息.

早期浏览器不断更新,支持的功能越来越丰富,新浏览器的功能多,旧浏览器的功能少,同一时刻,有的人用的是旧浏览器,有的人用的是新浏览器,服务器可以根据这个字段来判断是否要再这个浏览器带有某些功能

Referer

表示这个页面是从哪个页面跳转过来的,形如

https://v.bitedu.vip/login

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

Cookie

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

往往可以通过这个字段实现 “身份标识” 的功能.

每个不同的域名下都可以有不同的 Cookie, 不同网站之间的 Cookie 并不冲突.

【Java】应用层协议HTTP和HTTPS_第8张图片

正文(body)

正文中的内容格式和header中的Content-Type密切相关,上面也罗列了三种常见的情况

HTTP响应

HTTP状态码

常见的HTTP状态码

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

404 Not Found
没有找到资源

浏览器输入一个URL,目的就是为了访问对方服务器上的一个资源,如果这个URL标识的资源不存在,就会出现404
如果在浏览器中输入 www.sogou.com/index.html , 此时就在尝试访问 sogou 上的/index.html 这个资源.
如果输入正确就可以访问到,如果输入错误就会看到404这样的响应

403 Forbidden

标识访问被拒绝,有的页面通常需要用户具有一定的权限才能访问,如果没有权限直接访问,就容易见到403

405 Method Not Allowed
HTTP中的方法,例如GET,POST,PUT等方法,但是对方的服务器不一定都支持所有的方法,或者不允许用户使用一些其他的方法

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

504 Gateway Timeout

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

302 Move temporarily
HTTP状态码302是一个重定向状态码,代表暂时性转移(Temporarily Moved)。当一个网页使用HTTP状态码302作为响应时,它返回的不是任何HTML内容,而是包含了一个附加的HTTP报头信息:Location,它指示另一个URL地址,在那里可以找到响应的内容。

HTTP状态码302和301都代表重定向,但它们有一些区别。301代表永久性转移(Permanently Moved),而302代表暂时性转移(Temporarily Moved)。此外,除非被报头信息Cache-Control或Expires明确指定,否则客户不会缓存结果。因为302也用于一些付费广告的页面,主要用于跳转。

总之,HTTP状态码302是在满足某个HTTP请求时必须被发出另一个请求的重定向状态码,它指示暂时性转移至另一个URL。

301 Move Permanently
永久重定向 当浏览器受到这种响应后,后续的请求都会被自动改成新的地址

301 也是通过Location字段来表示要重定向到新的地址

【Java】应用层协议HTTP和HTTPS_第9张图片

响应报头(header)

响应报头的基本格式和请求报头的格式基本一致

类似于 Content-Type , Content-Length 等属性的含义也和请求中的含义一致.

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

text/html : body 数据格式是 HTML
text/css : body 数据格式是 CSS
application/javascript : body 数据格式是 JavaScript
application/json : body数据格式是 JSON

响应正文(body)

正文的具体格式取决于content-type

通过form表单构造HTTP请求

form (表单) 是 HTML 中的一个常用标签. 可以用于给服务器发送 GET 或者 POST 请求.

form发送GET请求

<form action="https://www.sogou.com/" method="GET">
	<input type="text" name="" id="">
    <input type="text" name="" id="">
    <input type="submit" name="" id="" value="提交">
form>

在这里插入图片描述
在输入框输入数据,提交后就会构造HTTP请求并发送出去
【Java】应用层协议HTTP和HTTPS_第10张图片

from的action属性对应HTTP请求的URL
form的method属性对应HTTP请求的方法
input的name属性对应query string的key
input的内容对应query string的value

form发送POST请求

<form action="https://www.sogou.com/" method="POST">
    <input type="text" name="userId" id="">
    <input type="text" name="userName" id="">
    <input type="submit" name="" id="" value="提交">
form>

【Java】应用层协议HTTP和HTTPS_第11张图片
和GET方法的区别
method从GET变成了POST
数据从query string移动到了body中

通过ajax构造HTTP请求

从前端角度, 除了浏览器地址栏能构造 GET 请求, form 表单能构造 GET 和 POST 之外, 还可以通过 ajax 的方式来构造 HTTP 请求. 并且功能更强大

ajax 全称 Asynchronous Javascript And XML, 是 2005 年提出的一种 JavaScript 给服务器发送
HTTP 请求的方式.
特点是可以不需要 刷新页面/页面跳转 就能进行数据传输.

在 JavaScript 中可以通过 ajax 的方式构造 HTTP 请求.

首先从jquery cdn上获取ajax资源
在这里插入图片描述

发送请求

【Java】应用层协议HTTP和HTTPS_第12张图片

在 j s 中 , 是一个合法的变量名 , 在js中,是一个合法的变量名, js,是一个合法的变量名,这个变量在jQuery中已经定义好的, 这个对象中就有很多方法 , 通过 这个对象中就有很多方法,通过 这个对象中就有很多方法,通过.的当时来调用对应的方法,$.ajax就是jQuery中封装好的,用来发起ajax请求的方法

通过这段代码,就可以向url所指向的地址发送一个请求,请求的内容是可自定义的

通过抓包工具可以获得我们发送的HTTP数据包,发现和我们指定的内容是一一对应的
【Java】应用层协议HTTP和HTTPS_第13张图片

通过第三方工具构造HTTP请求

通过postman工具也可以构造HTTP请求
【Java】应用层协议HTTP和HTTPS_第14张图片

HTTPS

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

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

加密

加密就是把明文(要进行传输的数据)进行一系列变换,生成密文,解密就是把密文在经历一系列变换还原成明文

在这个加密和解密的过程中, 往往需要一个或者多个中间的数据, 辅助进行这个过程, 这样的数据称为 密钥

HTTPS的工作过程

既然要保证数据安全, 就需要进行 “加密”.

网络传输中不再直接传输明文了, 而是加密之后的 “密文”.

加密的方式有很多, 但是整体可以分成两大类: 对称加密非对称加密

对称加密

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

一个简单的对称加密, 按位异或
假设 明文 a = 1234, 密钥 key = 8888
则加密 a ^ key 得到的密文 b 为 9834.
然后针对密文 9834 再次进行运算 b ^ key, 得到的就是原来的明文 1234.
(对于字符串的对称加密也是同理, 每一个字符都可以表示成一个数字)
当然, 按位异或只是最简单的对称加密. HTTPS 中并不是使用按位异或

【Java】应用层协议HTTP和HTTPS_第15张图片

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

但是事实上,一个服务器在同一时刻是需要给很多客户端提供服务的,这么多的客户端,每个人需要的密钥都必须是不同的,因此服务器就需要维护每个客户端和每个密钥之间的关联关系

理想的做法是,在客户端和服务器建立连接的时候,双方协商确定这次的密钥是什么

【Java】应用层协议HTTP和HTTPS_第16张图片
但是又出现了一个问腿,如果我们直接把密钥明文传输,就得到了和最开始一样的问题,当我们的密钥被黑客截获之后,我们就算加密传输,但是因为黑客手上保留有密钥,我们就相当于明文传输了

我们可以想到给密钥在加密?
这样就会进入到一种无限循环的过程中,此时就需要引入非对称加密

非对称加密

非对称加密要用到两个密钥, 一个叫做 “公钥”, 一个叫做 “私钥”.
公钥和私钥是配对的. 最大的缺点就是运算速度非常慢,比对称加密要慢很多.

  • 通过公钥对明文加密, 变成密文
  • 通过私钥对密文解密, 变成明文
    也可以反着用
  • 通过私钥对明文加密, 变成密文
  • 通过公钥对密文解密, 变成明文

非对称加密的数学原理比较复杂, 涉及到一些 数论 相关的知识. 这里举一个简单的生活上的例子.
A 要给 B 一些重要的文件, 但是 B 可能不在. 于是 A 和 B 提前做出约定:
B 说: 我桌子上有个盒子, 然后我给你一把锁, 你把文件放盒子里用锁锁上, 然后我回头拿着钥匙来开锁取文件.
在这个场景中, 这把锁就相当于公钥, 钥匙就是私钥. 公钥给谁都行(不怕泄露), 但是私钥只有 B 自己持有. 持有私钥的人才能解密

【Java】应用层协议HTTP和HTTPS_第17张图片

客户端在本地生成对称密钥,通过公钥加密,发送给服务器
犹豫中间的网络设备没有私钥,即使截获了数据,也无法还原出内部的原文,也就无法获取到对称密钥
服务器持有私钥,通过私钥还原出客户端发送的对称密钥,并且使用这个对称密钥加密给客户端返回的响应数据
后续客户端和服务器的通信都只用对称密钥加密即可,由于这个密钥只有客户端和服务器两个人知道,所以其他设备截获数据也没有意义

但是问题在于,客户端如何获取公钥,且这个公钥不是黑客伪造的

证书

在客户端和服务器刚一建立连接的时候, 服务器给客户端返回一个 证书. 这个证书包含了刚才的公钥, 也包含了网站的身份信息.

【Java】应用层协议HTTP和HTTPS_第18张图片
这个整数可以理解成是一个结构化的字符串,包含了

  • 证书发布机构
  • 证书有效期
  • 公钥
  • 证书所有者
  • 签名

当客户端获取到这个证书之后, 会对证书进行校验(防止证书是伪造的).

判定证书的有效期是否过期
判定证书的发布机构是否受信任(操作系统中已内置的受信任的证书发布机构).
验证证书是否被篡改: 从系统中拿到该证书发布机构的公钥, 对签名解密, 得到一个 hash 值(称为数据摘要), 设为 hash1. 然后计算整个证书的 hash 值, 设为 hash2. 对比 hash1 和 hash2 是否相等. 如果相等, 则说明证书是没有被篡改过的

数据摘要和签名

签名在一定程度上区分不同的数据,常见的生成签名的算法有MD5和SHA系列
以MD5为例,它的特点是

  • 定长:无论多长的字符串,计算出来的MD5值都是固定长度(16字节或者32字节)
  • 分散:源字符串只要改变一点点,最终得到的MD5值都会差别很大
  • 不可逆:通过原字符串生成MD5很容易,但是通过MD5还原成源字符串理论上来说是不可能的
    所以我们认为,如果两个字符串的MD5值相同,就认为这两个字符串相同

如何判定证书是否被篡改呢?
假设我们传入字符串1,根据这个字符1计算出hash1
我们就可以将字符串1和hash1从服务器传输给客户端,
此时客户端通过字符串1再次计算hash1,因为MD5的特点是分散和不可逆,如果有黑客篡改了字符串1的值,此时客户端根据这个字符串计算出来的hash值不是传输过来的hash1,就可以判断数据是否被篡改

此时又出现一个问题,如果黑客篡改了字符串1,
所以被传输的hash值不能明文传输,也需要传输密文
这个hash值在服务器端通过另一个私钥加密(这个私钥是申请证书的时候,证书发布机构给服务器的,不是客户端和服务器传输对称密钥的私钥)
客户端通过操作系统里的已经存的了证书发布机构的公钥进行解密,还原出原始的hash值,再进行校验

【Java】应用层协议HTTP和HTTPS_第19张图片

总结

HTTPS 工作过程中涉及到的密钥有三组.

第一组(非对称加密): 用于校验证书是否被篡改. 服务器持有私钥(私钥在注册证书时获得), 客户端持有公钥(操作系统包含了可信任的 CA 认证机构有哪些, 同时持有对应的公钥). 服务器使用这个私钥对证书的签名进行加密. 客户端通过这个公钥解密获取到证书的签名, 从而校验证书内容是否是篡改过.
第二组(非对称加密): 用于协商生成对称加密的密钥. 服务器生成这组 私钥-公钥 对, 然后通过证书把公钥传递给客户端. 然后客户端用这个公钥给生成的对称加密的密钥加密, 传输给服务器, 服务器通过私钥解密获取到对称加密密钥.
第三组(对称加密): 客户端和服务器后续传输的数据都通过这个对称密钥加密解密.

你可能感兴趣的:(Java,网络,http,java,https)