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

HTTP 往往是基于传输层的 TCP 协议实现的
HTTP的工作原理
HTTP使用一问一答模式的协议,客户端发一个请求,服务器就返回一个响应,请求和响应是一一
对应的关系
事实上, 当我们访问一个网站的时候, 可能涉及不止一次的 HTTP 请求/响应的交互过程
多问一答
例如:上传大文件
一问多答
例如:下载大文件
多问多答
例如:远程控制
HTTP 协议格式
HTTP 是一个文本格式的协议. 可以通过 Chrome 开发者工具或者 Fiddler 抓包, 分析 HTTP 请求/
响应的细节
抓包工具
这种抓包工具能够获取到网络的数据包详细的格式都解析出来了,抓包工具相当于"代理"

左侧窗口是当前的请求和响应(注意此处的fidder只抓http)
对于fiddler左侧窗口中不同颜色表示的数据行含义不相同
蓝色的表示这个请求得到了个网页
绿色表示得到个js
灰色的表示这个响应的数据已经被缓存了
抓包结果
请求结果

随机抓取一个网页的内容,通过指定路径抓定显示请求的原始数据


对于这样一个响应,我们要把它区分来看
(1)首行
构成:请求方法 URL 版本号

(2)请求头(header)
构成:键值对结构,每一行是一个键值对结构,键和值之间使用特定字符串分开

(3)空行
用来表示header结束了

(4)正文(body)
有些请求有正文,有些没有正文

响应结果
响应数据经常是被压缩后传输的,这是为了节省更多网络宽带


与请求一样,相应也可以分为四个部分
(1)首行

(2)响应头(header)
也是键值对,涉及到的键值对和请求是有区别的(有些重要的件之对,可能同时在请求和响应都存
在)

(3)空行
标识header部分不同

(4)正文(body)
这个响应来说,body是一个html

请求与响应
|-----|-----|
| 请求 | 响应 |
| 首行 | 首行 |
| 请求头 | 响应头 |
| 空行 | 空行 |
| 正文 | 正文 |
HTTP 请求
URL
URL是描述网络上的唯一资源的位置,以JDBC中运用到的URL为例:

URL 基本格式
1. 协议部分 (jdbc:mysql)
- 标签: 协议名称
- 说明: URL 不是 HTTP 专属的概念,可以给各种协议提供支持。
2. 主机地址部分 (127.0.0.1)
- 标签: 要访问的服务器的 ip 地址或者域名
- 说明:
- 域名和 ip 可以相互转换。
- 这个过程通过 DNS 域名解析系统来完成的(DNS 既是一套服务器系统,也是一种应用层协议)。
- 通过 IP 定位到一台主机了。
- 同一个主机上是有多个程序都在使用网络,通过端口号来进一步区分,每个程序使用网络的时候都会关联一个空闲的端口号
3. 端口部分 (3306)
- 标签: 端口号 区分哪个应用程序
4. 路径部分 (java113)
- 标签: 带有层次结构的路径
- 说明:
- 想要访问的是,某个主机上某个程序注册的某个资源
- 每一层就相当于目录,目录里面还可以有子目录
- 可以是一个硬盘上的文件,也可以是虚拟的资源(通过一段代码逻辑来生成的数据)
5. 查询参数部分 (?characterEncoding=utf8&useSSL=false)
- 标签: 查询字符串 Query String
- 说明:
- 对要访问的资源补充说明
- 也是键值对结构,键值对之间使用
&分割,键和值之间使用=分割 - 此处键值对的咋写都是程序员自定义的
补充说明
对于一些特殊的HTTP和HTTPS的URL,当没出现端口号的时候,浏览器会自动默认添加那个端
口
HTTP = > 80
HTTPS = > 443
访问远端服务器的那个端口,不是浏览器自身的"客户端的端口"

登录信息:现在登录认证信息不会写到url中
片段标识符:区分当前这个页面的哪个部分的,一般在文档类的网站进行使用
query string 的内容程序员自定义的,万一 query string里也包含了特殊含义的符号咋办?
URL encode
像 / ? : 等这样的字符, 已经被url当做特殊意义理解了. 因此这些字符不能随意出现
转义操作, 不仅仅是标点符号,对于中文等其他非英语系的文字也是需要转义的,只不过很多浏览器
为了用户看起来方便,显示的时候显示转义之前的。实际上,抓包中看到是已经转义的数据。
比如, 某个参数中需要带有这些特殊字符就必须先对特殊字符进行转义.

没有进行转义操作可能会出现请求失败的情况
转义的规则
urlendcode 把数据的二进制内容每个字节取出来 十六进制表示, 前面加上 %
认识 "方法"

上面我们常用的方法主要有四个
GET
POST
PUT
DELETE
GET 方法
GET 是最常用的 HTTP 方法,常用于获取服务器上的某个资源。在浏览器中直接输入 URL, 此时
浏览器就会发送出一个 GET 请求。另外, HTML 中的 link, img, script 等标签, 也会触发 GET 请求.

GET 请求的特点
- 首行的第一部分为 GET
- URL 的 query string 可以为空, 也可以不为空.
- header 部分有若干个键值对结构.
- body 部分为空(GET请求一般都是没有body的,如果需要通过GET发送数据需要借助query string)
POST 方法
POST 方法也是一种常见的方法. 多用于提交用户输入的数据给服务器(例如登陆页面)
两个典型场景
登录和上传,请求是带有正文的,正文就是保存了当前上传的数据的内容
POST 请求的特点
首行的第一部分为 POST
URL 的 query string 一般为空 (也可以不为空)
header 部分有若干个键值对结构.
body 部分一般不为空,body 内的数据格式通过 header 中的 Content-Type 指定,body 的长度由 header 中的 Content-Length 指定.
GET与POST区别
1.语义上,语义上可以混着用
2.携带数据方式,POST也是可以带有query string(还是有一些的),GET理论上也可以带body(更少
见)
3.GET请求通常建议设计成幂等性,POST无要求
4.GET设计成幂等性就可以允许GET请求地结果被缓存;POST由于不要求幂等性经常是不幂等
的,就认为是不能被缓存的
5.获取html,css,js都是get,登录,上传文件都是用post
补充说明
-
POST 比 GET 更安全
在登录场景输入用户名和密码。GET, 用户名密码就会放到 url 的 query string中, 就会显示在浏览器地址栏上了。事实上为了保证安全, 关键是 "加密传输"。POST 传输如果不加密, 黑客随便抓个包也就看到了,只要明文传输都谈不上安全
-
GET 传输数据有长度限制
在使用 IE 浏览器的年代, IE6(windows xp) 对于 URL 的长度是有限制的,此时如果传输的数据太多可能就会被截断。现在的主流浏览器/服务器早都没有这样的限制了,比较长的 URL 很多时候也能见到
-
GET 只能传输文本, POST 可以传输二进制
GET 确实 url 只能放文本. 可以把二进制通过 base64 转码成文本的,GET的query string 虽然无法直接传输二进制数据, 但是可以针对二进制数据进行urlencode.
PUT和DELETE
对于这两个方法,一般在实现Restful风格的api的时候会用到,设计成服务器接口的一种习惯
认识请求 "报头" (header)
header 的整体的格式是键值对结构,分成很多行, 每一行是一个键值对
键和值之间使用" : "或者 空格 分割
Host
表示服务器主机的地址和端口(IP地址(域名) : 端口号)

HOST与URL
大部分情况下二者属性是一致的,但是在有一些特殊场景下是不一致的,当使用了代理的情况下,
HOST可以获取最原始的数据
HTTP 协议中, 传输的时候可能会涉及到 "加密" (HTTPS),URL 部分是不会被加密的,被加密的是 header 和 body
服务器收到请求之后也就可以做一个最终校验,验证 url 中的内容和 header 中加密的内容是否一
致
Content-Length
表示 body 中的数据长度
HTTP 协议, 传输层这里基于 TCP 实现的,所谓的 HTTP 协议, 就是把字符串构造成 HTTP 约定的
格式
- 首行 方法 url 版本号
- 请求头 键值对
- 空行
- 正文
当把这一串字符串写入到 tcp socket 中,对于 TCP 来说 一个连接上可以发多个请求,服务器这边
收到数据的时候就得区分一下, 从哪里到哪里是一个完整的 http 请求数据
没有 body 的 http 请求读到空行就可以认为是结束了.
有 body 的 http 请求呢? 先读取首行和 header, 读到空行; 解析 header 中的 Content-Length根据这
里的值, 接下来再读取固定字节的长度
而对于UDP,UDP 是面向数据报的,读写的基本单位就是一个 UDP 数据报,如果某个应用层协
议基于 UDP, 一个 UDP 数据报就对应一个完整的应用层数据包,调用一次 receive 操作就得到一
个明确的 UDP 的数据包
Content-Type
表示请求的 body 中的数据格式,提示了接收方如何解析 body 中的数据
HTTP 这里面能够携带的数据种类是比较多
|----------|------------------------|
| 数据类型 | Content-Type |
| HTML | text/html |
| CSS | text/css |
| JS | application/javascript |
| JSON | application/json |
| 图片 | image/png image/jpg |
请求和响应都会用到这两个 header,如果有 body并且没有这俩属性 (哪怕只有一个) 都认为是非法的/错误的http报文
User-Agent (简称 UA)
表示浏览器/操作系统的属性和情况

User-Agent 之所以是这个样子是因为历史遗留问题,但随着不断发展UA开始用来区分用户的设
备,根据用户的设备返回不同的版本页面
Referer
表示这个页面是从哪个页面跳转过来的,直接输入URL/点收藏栏,打开的页面是没有Referer

Cookie
浏览器展示页面的过程中, 页面里虽然可以通过 js 来实现一些逻辑,但是浏览器给 js做出了限
制(怕 js 要是能操作用户文件系统, 直接篡改系统文件), js 代码无法访问你的硬盘的(文件系统),
实际开发中, 有的时候还是希望把某些数据能够保存到本地硬盘的,因此浏览器引入了 cookie 机制
Cookie作用
cookie 就是浏览器允许网页在本地硬盘存储数据的一种机制,不是让网页代码直接访问文件系统
做了一层抽象,而是浏览器的 cookie 提供了键值对存储机制
Cookie 这里是按照键值对的方式来存储数据的
- url 的 query string 程序员自定义
- header 部分也是键值对 标准规定
- header 中 cookie 里存的数据还是键值对 程序员自定义
- body 是 json 格式, 仍然是键值对 程序员自定义
结合实际情况, 基于 HTTP 实现一些个性化的功能需求
抓包工具中的cookie

浏览器中可以直接看到当前页面保存的cookie那些的

cooker按照域名维度来组织的
浏览器保存了这些 cookie 之后, 就会在后续给服务器发送请求的时候,把这些 cookie 键值对放到 请求 cookie header 中传输给服务器
Cookie 到哪里去: 最终发回给服务器.
Cookie 从哪里来: 也是从服务器这边来的. (后端开发程序员, 决定的)
cookie的运用---登录

对于这样一个登陆界面
当客户端发送登录请求时,服务器会查询数据库,验证你的用户名密码是否有效,如果匹配成功
- 生成 sessionId
- 生成 session 对象
- 把用户的关键信息保存到 session 对象中
- 把 sessionId 和 session 对象作为键值对,保存到内存的 hash 表中
- 把 sessionId, 通过 Set-Cookie 返回给浏览器
服务器收到后续请求之后直接通过 cookie 中的 sessionId,就可以知道当前这个请求是哪个用户发
来的了,就不需要要求用户重新登陆
会话
session 对象也是可以存储用户自定义的数据的,表示了当前这一次会话的详细信息
补充
Cookie 是可能会过期的,服务器返回 Cookie 的时候是可以设置有效时间,如果 Cookie 中的
sessionId 过期了, 此时就需要用户重新登陆了.
有的网站, 对于安全性要求不高, 过期时间就长
有的网站, 对于安全性要求很高, 过期时间就短
请求头的关键属性
|----------------|----------------------------------------------------------------------------------------------------------------------------------|
| Host | 访问的服务器的 主机ip 和端口 |
| Content-Length | body 的长度 (字节) |
| Content-Type | body 的数据格式. html, css, js, json, 图片 |
| Referer | 当前页面从哪里跳转过来的 |
| User-Agent | 描述当前上网的设备的操作系统和浏览器信息 |
| Cookie | 浏览器在本地存储数据的一种方式~~ 键值对 服务器通过 Set-Cookie 返回的. 后续给服务器发的请求, 都会带上 Cookie 按照域名为维度, 以键值对的方式来存储 Cookie 中的内容都是 程序员自定义. 最典型的场景, 实现登录身份认证 |
HTTP 响应详解
认识 "状态码"
状态码表示访问一个页面的结果. (是访问成功, 还是失败, 还是其他的一些情况...)

200 OK
最常见的状态码,表示成功

404 Not Found
表示访问资源没有找到
浏览器输入一个 URL, 目的就是为了访问对方服务器上的一个资源. 如果这个 URL 标识的资源不存
在, 那么就会出现 404
URL中的ip定位到主机,port定位到程序,path定位到程序管理的资源(404标识path访问的资源在
服务器上没有)
403 Forbidden
表示访问被拒绝. 有的页面通常需要用户具有一定的权限才能访问(登陆后才能访问). 如果用户没有登陆 直接访问, 就容易见到 403
405 Method Not Allowed
请求的方法和服务器这边声明注释不匹配就会出现405
500 Internal Server Error
服务器出现内部错误,服务器处理逻辑的代码中抛出异常,但是你没有catch到, 一般是服务器的
代码执行过程中遇到了一些特殊情况(服务器异常崩溃)会产生这个状态码
504 Gateway Timeout
当服务器负载比较大的时候, 服务器处理单条请求的时候消耗的时间就会很长, 就可能会导致出现超时的情况.
302 Move temporarily
临时重定向
理解 "重定向"
当有网站进行域名迁移时,旧域名就无法访问了,但可以把服务器架设在新域名上,给旧域名设置
重定向,可以重定向到新域名。当访问旧域名时自动跳转到新域名
301 Moved Permanently
永久重定向. 当浏览器收到这种响应时, 后续的请求都会被自动改成新的地址. 301 也是通过
Location 字段来表示要重定向到的新地址.
状态码小结
| 类别 | 原因短语 | |
|---|---|---|
| 1XX | Informational(信息性状态码) | 接收的请求正在处理 |
| 2XX | Success(成功状态码) | 请求正常处理完毕 |
| 3XX | Redirection(重定向状态码) | 需要进行附加操作以完成请求 |
| 4XX | Client Error(客户端错误状态码) | 服务器无法处理请求 |
| 5XX | Server Error(服务器错误状态码) | 服务器处理请求出错 |
通过 Java socket 构造 HTTP 请求
HTTP 请求, 本质上就是 TCP 请求,只需要构造字符串符合 HTTP 协议格式,写入到 TCP socket
中

读到的响应字符串要符合HTTP协议响应报文结构的内容
其他构造HTTP请求的方法:
apifox构造HTTP请求
Postman构造HTTP请求
HTTPS
HTTPS 是什么
HTTPS 也是一个应用层协议,是在 HTTP 协议的基础上引入了一个加密层。HTTP 协议内容都是
按照文本的方式明文传输的,这就导致在传输过程中出现一些被篡改的情况
"加密" 是什么
加密就是把 明文 (要传输的信息)进行一系列变换, 生成密文 .
解密就是把 密文 再进行一系列变换, 还原成明文
HTTPS 的工作过程
既然要保证数据安全, 就需要进行 "加密".
网络传输中不再直接传输明文了, 而是加密之后的 "密文".
加密的方式有很多, 但是整体可以分成两大类: 对称加密 和 非对称加密
对称加密
对称加密其实就是通过同一个 "密钥" , 把明文加密成密文, 并且也能把密文解密成明文.
加密和解密都是使用同一个密钥
非对称加密
加密使用一个密钥,解密使用另一个密钥,存在关联关系很难猜
当把其中公开出去,此时称为公钥;另一个自己保存好,称为私钥
当公钥加密时,私钥解密;当私钥加密,公钥解密
对称和非对称加密的运用
当未引入对称和非对称加密,都是明文传输

此时黑客很容易获取到传输的数据内容,也很容易进行篡改
引入对称加密

如果不知道key是啥就无法对数据进行解密,无法理解数据的含义更不必说篡改了
多个客户端, 密钥是相同还是不同?
必须是不同的,如果大家都是相同的密钥,意味着黑客自己搞个客户端就拿到密钥了
非对称密钥的引入
客户端和服务器最开始通信的时候, 就需要一方生成唯一的密钥, 再通过网络传输给另一方
假设客户端生成

此时就需要对密钥进行加密,如果仍然使用对称加密的方式, 生成一个 key2 对称密钥, 使用
key2对 key 进行加密,但key2还是得传给服务器仍会泄露。
此时引入非对称加密就是为了解决密钥传输的安全性问题

在这里,公钥相当于一把锁,私钥相当于对应的钥匙
由于黑客手里没有私钥,所以黑客不能对 888888 加密后的数据进行解密的,此时数据到达服务
器,服务器使用自己的私钥解密,就知道了对称密钥是多少了
那为什么不直接全用非对称加密?
实际情况时需要对称加密,因为对称加密速度快,适合针对大量数据加密;非对称加密运算速度
快,开销大,加密小的数据时还行,当加密大量数据就会很耗时
当前的场景有三个密钥
- 客户端生成的对称密钥
- 服务器生成的公钥, 可以给所有设备告知
- 服务器生成的私钥, 只有自己知道
中间人攻击
黑客可以使用中间人攻击, 获取到对称密钥

黑客自己生成一对公钥私钥pub2,pri2
pub1被黑客拦截下来,改成了pub2,此时key是通过pub2来加密的,黑客自己就可以使用配对的
pri2解密,黑客自然就拿到key了,黑客继续使用服务器的pub1,对key重新加密继续转发给服务器
此时客户端与服务器之间的通信就泄露了
引入证书
服务端在使用HTTPS前,需要向公证机构申领一份数字证书,数字证书里含有证书申请者信息、
公钥信息等。服务器把证书传输给浏览器,浏览器从证书里获取公钥就行了,证书就如身份证,证
明服务端公钥的权威性

数字签名本质上就是一个被加密的校验和,将要校验的数据部分代入一个固定的公式算出一个数字
输入的值相同的得到的校验和就是相同的,输入的值不相同得到的校验和大概率不相同,如果发现
校验和不同,输入的初始值就是不同的
客户端收到证书, 就要进行校验
1.客户端需要针对证书中的其他字段
- 证书的颁布机构是谁;证书的有效期是啥时候;服务器的公钥是谁;服务器的拥有者 (域名) 是啥
- 使用同样的算法, 再算一次校验和. 得到了校验和1 ------> 针对客户端收到的数据进行计算的
2.在通过公正机构的公钥 pub2, 对数字签名进行解密, 得到校验和2 ------> 服务器申请证书的时候
得到的原始校验和
3.对比校验和1和校验和2是否相同,如果相同说明证书是没有被修改过的,如果不同, 证书无效中
间被人篡改了。如果校验和一样 就说明客户端收到的数据是原始数据
客户端如何确保拿到的pub2是公证机构的pub2,而不是黑客伪造的 pub2 呢?
pub2 就不是通过网络传输的. 而是操作系统中内置的(安装好系统, 系统就内置了一系列知名公正机
构的公钥),只要安装正版系统,不是黑客搞的盗版系统就可以信任 pub2 是正确合法的
加密总结
- 引入对称加密
- 引入非对称加密
- 中间人攻击
- 引入证书和数字证明
加密是SSL的握手流程,不只局限于HTTPS的,其他基于SSL的网络协议也是类似流程